How to deserialize an empty JSON string to null for java.lang.String?

I am trying simple JSON to de-serialize into a java object. However, I get empty String values ​​for the values ​​of the java.lang.String property. In the rest of the properties, null values ​​are converted to null values ​​(this is what I want).

My JSON and its associated Java class are listed below.

JSON string:

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

EventBean POJO Class:

 public class EventBean { public Long eventId; public String title; public String location; } 

My main code is:

 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 a print of "This is Zero." Instead, I get "This." Obviously, Jackson does not treat empty String values ​​as NULL when converting to my String object type.

I read somewhere that this was expected. However, this is what I want to avoid for java.lang.String too. Is there an easy way?

+13
java json jackson
source share
3 answers

Jackson will give you null for other objects, but for String he will give an empty string.

But you can use Custom JsonDeserializer for this:

 class CustomDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { JsonNode node = jsonParser.readValueAsTree(); if (node.asText().isEmpty()) { return null; } return node.toString(); } } 

In the class, you should use it for the location field:

 class EventBean { public Long eventId; public String title; @JsonDeserialize(using = CustomDeserializer.class) public String location; } 
+8
source share

You can define your own deserializer for the String type by 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); 

Thus, all string fields will behave the same.

+10
source share

For those using Spring Boot: the answer from jgesser was most useful to me, but I spent some time trying to develop a better way to configure it in Spring Boot.

In fact, the documentation says:

Any components of type com.fasterxml.jackson.databind.Module are automatically registered using the autoconfigured Jackson2ObjectMapperBuilder and apply to any ObjectMapper instances that it creates.

So here jgesser answer has expanded to what 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; } } 
0
source share

All Articles