Может ли Джексон быть настроен на обрезание начальных / конечных пробелов из всех свойств строки? - PullRequest
35 голосов
/ 28 июля 2011

Пример JSON (обратите внимание, что в строке есть завершающие пробелы):

{ "aNumber": 0, "aString": "string   " }

В идеале десериализованный экземпляр должен иметь свойство aString со значением "string" (т.е. без конечных пробелов). Это похоже на то, что, вероятно, поддерживается, но я не могу его найти (например, в DeserializationConfig.Feature ).

Мы используем Spring MVC 3.x, поэтому решение на основе Spring также подойдет.

Я попытался настроить WebDataBinder Spring на основе предложения в сообщении на форуме , но, похоже, он не работает при использовании конвертера сообщений Джексона:

@InitBinder
public void initBinder( WebDataBinder binder )
{
    binder.registerCustomEditor( String.class, new StringTrimmerEditor( " \t\r\n\f", true ) );
}

Ответы [ 5 ]

19 голосов
/ 17 ноября 2015

Простое решение для пользователей Spring Boot, просто добавьте расширение SimpleModule для Walv в контекст приложения:

package com.example;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class StringTrimModule extends SimpleModule {

    public StringTrimModule() {
        addDeserializer(String.class, new StdScalarDeserializer<String>(String.class) {
            @Override
            public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException,
                    JsonProcessingException {
                return jsonParser.getValueAsString().trim();
            }
        });
    }
}

Другой способ настроить Джексона - добавить компоненты типа com.fasterxml.jackson.databind.Module для вашего контекста.Они будут зарегистрированы с каждым компонентом типа ObjectMapper, предоставляя глобальный механизм для добавления пользовательских модулей при добавлении новых функций в ваше приложение.

http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper

, если вы не с использованием весенней загрузки, вы должны зарегистрировать StringTrimModule самостоятельно (вам не нужно аннотировать его с помощью @Component)

<bean class="org.springframework.http.converter.json.Jackson2Objec‌​tMapperFactoryBean">
    <property name="modulesToInstall" value="com.example.StringTrimModule"/>
</bean
16 голосов
/ 09 августа 2011

С помощью пользовательского десериализатора вы можете сделать следующее:

 <your bean>
 @JsonDeserialize(using=WhiteSpaceRemovalSerializer.class)
 public void setAString(String aString) {
    // body
 }

 <somewhere>
 public class WhiteSpaceRemovalDeserializer extends JsonDeserializer<String> {
     @Override
     public String deserialize(JsonParser jp, DeserializationContext ctxt) {
         // This is where you can deserialize your value the way you want.
         // Don't know if the following expression is correct, this is just an idea.
         return jp.getCurrentToken().asText().trim();
     }
 }

Это решение подразумевает, что этот атрибут компонента всегда будет сериализован таким образом, и вам придется аннотироватькаждый атрибут, который вы хотите десериализовать таким образом.

14 голосов
/ 06 июня 2014

Проблема аннотации @JsonDeserialize заключается в том, что вы всегда должны помнить о том, чтобы поставить ее на установщик.Чтобы сделать это глобально «раз и навсегда» с Spring MVC, я сделал следующие шаги:

pom.xml:

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.3.3</version>
</dependency>

Создание пользовательского ObjectMapper:

package com.mycompany;

    import java.io.IOException;
    import org.apache.commons.lang3.StringUtils;
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
    import com.fasterxml.jackson.databind.module.SimpleModule;

    public class MyObjectMapper extends ObjectMapper {

        public MyObjectMapper() {
            registerModule(new MyModule());
        }
    }

    class MyModule extends SimpleModule {

        public MyModule() {
            addDeserializer(String.class, new StdScalarDeserializer<String>  (String.class) {
                @Override
                public String deserialize(JsonParser jp, DeserializationContext  ctxt) throws IOException,
                    JsonProcessingException {
                    return StringUtils.trim(jp.getValueAsString());
                }
            });
        }
    }

Обновите сервлет-context.xml в Spring:

<bean id="objectMapper" class="com.mycompany.MyObjectMapper" />

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper" ref="objectMapper" />
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
4 голосов
/ 13 июля 2017

Для Spring Boot нам просто нужно создать собственный десериализатор как , описанный в руководстве .

Ниже приведен мой код Groovy, но вы можете свободно адаптировать его для работы в Java.

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import org.springframework.boot.jackson.JsonComponent

import static com.fasterxml.jackson.core.JsonToken.VALUE_STRING

@JsonComponent
class TrimmingJsonDeserializer extends JsonDeserializer<String> {

    @Override
    String deserialize(JsonParser parser, DeserializationContext context) {
        parser.hasToken(VALUE_STRING) ? parser.text?.trim() : null
    }
}
3 голосов
/ 21 сентября 2018

com.fasterxml.jackson.dataformat

pom.xml

   <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-csv</artifactId>
      <version>2.5.3</version>
    </dependency>

CsvUtil.java

     CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader().sortedBy();
     CsvMapper mapper = new CsvMapper();
     mapper.enable(CsvParser.Feature.TRIM_SPACES);
     InputStream inputStream = ResourceUtils.getURL(fileName).openStream();
     MappingIterator<T> readValues =
          mapper.readerFor(type).with(bootstrapSchema).readValues(inputStream);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...