Can Jackson be configured to trim leading/trailing whitespace from all string properties?

Viewed 52016

Example JSON (note that the string has trailing spaces):

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

Ideally, the deserialised instance would have an aString property with a value of "string" (i.e. without trailing spaces). This seems like something that is probably supported but I can't find it (e.g. in DeserializationConfig.Feature).

We're using Spring MVC 3.x so a Spring-based solution would also be fine.

I tried configuring Spring's WebDataBinder based on a suggestion in a forum post but it does not seem to work when using a Jackson message converter:

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

I think it is better to extend default StringDeserializer as it already handles some specific cases (see here and here) that can be used by third party libraries. Below you can find configuration for Spring Boot. This is possible only with Jackson 2.9.0 and above as starting from 2.9.0 version StringDeserializer is not final anymore. If you have Jackson version below 2.9.0 you can still copy content of StringDeserializer to your code to handle above mentioned cases.

@JsonComponent
public class StringDeserializer extends com.fasterxml.jackson.databind.deser.std.StringDeserializer {

    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String value = super.deserialize(p, ctxt);
        return value != null ? value.trim() : null;
    }
}

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);
Related