37

I am trying a simple JSON to de-serialize in to java object. I am however, getting empty String values for java.lang.String property values. In rest of the properties, blank values are converting to null values(which is what I want).

My JSON and related Java class are listed below.

JSON string:

{
  "eventId" : 1,
  "title" : "sample event",
  "location" : "" 
}

EventBean class POJO:

public class EventBean {

    public Long eventId;
    public String title;
    public String location;

}

My main class code:

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

try {
    File file = new   File(JsonTest.class.getClassLoader().getResource("event.txt").getFile());

    JsonNode root = mapper.readTree(file);
    // find out the applicationId

    EventBean e = mapper.treeToValue(root, EventBean.class);
    System.out.println("It is " + e.location);
}

I was expecting print "It is null". Instead, I am getting "It is ". Obviously, Jackson is not treating blank String values as NULL while converting to my String object type.

I read somewhere that it is expected. However, this is something I want to avoid for java.lang.String too. Is there a simple way?

5 Answers 5

37

Jackson will give you null for other objects, but for String it will give empty String.

But you can use a Custom JsonDeserializer to do this:

class CustomDeserializer extends JsonDeserializer<String> {

    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
        JsonNode node = jsonParser.readValueAsTree();
        if (node.asText().isBlank()) {
            return null;
        }
        return node.toString();
    }

}

In class you have to use it for location field:

class EventBean {
    public Long eventId;
    public String title;

    @JsonDeserialize(using = CustomDeserializer.class)
    public String location;
}
Sign up to request clarification or add additional context in comments.

7 Comments

This worked for me too, but using readValueAsTree() wrapped the string in extra quotes. So to avoid it I used instead jsonParser.readValueAs(String.class);
@kopelitsa extra quotes issue could be resolved by "return node.asText();"
Can we apply the JsonDeserialize annotation to class level also , so that all the string attributes with empty string under that will convert to null ?
@AnsarSamad Did you have an answer to your question? I would need to understand if it can be inserted at the class level
@Jacket yes it also works on the class level for all String fields.
|
24

It is possible to define a custom deserializer for the String type, overriding the standard String deserializer:

this.mapper = new ObjectMapper();

SimpleModule module = new SimpleModule();

module.addDeserializer(String.class, new StdDeserializer<String>(String.class) {

    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String result = StringDeserializer.instance.deserialize(p, ctxt);
        if (StringUtils.isEmpty(result)) {
            return null;
        }
        return result;
    }
});

mapper.registerModule(module);

This way all String fields will behave the same way.

Comments

10

You might first like to see if there has been any progress on the Github issue requesting this exact feature.

For those using Spring Boot: The answer from jgesser was the most helpful to me, but I spent a while trying to work out the best way to configure it in Spring Boot.

Actually, the documentation says:

Any beans of type com.fasterxml.jackson.databind.Module are automatically registered with the auto-configured Jackson2ObjectMapperBuilder and are applied to any ObjectMapper instances that it creates.

So here's jgesser's answer expanded into something you can copy-paste into a new class in a Spring Boot application

@Configuration
public class EmptyStringAsNullJacksonConfiguration {

  @Bean
  SimpleModule emptyStringAsNullModule() {
    SimpleModule module = new SimpleModule();

    module.addDeserializer(
        String.class,
        new StdDeserializer<String>(String.class) {

          @Override
          public String deserialize(JsonParser parser, DeserializationContext context)
              throws IOException {
            String result = StringDeserializer.instance.deserialize(parser, context);
            if (StringUtils.isEmpty(result)) {
              return null;
            }
            return result;
          }
        });

    return module;
  }
}

1 Comment

Alas, the issue you're referring to has been closed by (one of) the maintainer(s) due to seemingly apparent lack of interest...
3

I could get this by following configuration.

final ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);

1 Comment

This doesn't work - that deserialization feature is intended just for empty strings as the whole JSON expression (indicated by that "NULL_OBJECT") - not for object attributes.
1

it is possible to use JsonCreator annotation. It worked for me

public class Foo {
private String field;

 @JsonCreator
 public Foo(
   @JsonProrerty("field") String field) {
     this.field = StringUtils.EMPTY.equals(field) ? null : field ;
}
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.