Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell Jackson to deserialize "null" string to null literal?

I have a webservice which prints "null" as a string for any property instead of null literal. It does that for almost all data types(String or Date). For example, in ideal case it returns

{
    "item" : {
        "title": "Some title",
        "expires": "2014-11-02 00:00:00"
    }
}

But sometimes it returns:

{
    "item" : {
        "title": "null",
        "expires": "2014-11-02 00:00:00"
    }
}

Which makes the title property value as "null" instead of setting it to null. Or sometime this:

{
    "item" : {
        "title": "Some title",
        "expires": "null"
    }
}

Which makes the deserialization fail because the dateformat does not match. How can I configure objectmapper or annotate my model classes to resolve these problems during deserialization?

My model class looks like:

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Item {
    public String title;
    @JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
    public Date expires;
}

It's an android app so I have no control over the webservice. Thanks in advance

like image 711
Max Avatar asked Sep 17 '14 01:09

Max


People also ask

How does Jackson serialize null?

Serialize Null Fields Fields/PropertiesWith its default settings, Jackson serializes null-valued public fields. In other words, resulting JSON will include null fields. Here, the name field which is null is in the resulting JSON string.

How do you tell Jackson to ignore a field during Deserialization if its value is null?

Jackson default include null fields 1.2 By default, Jackson will include the null fields. To ignore the null fields, put @JsonInclude on class level or field level.

How do I ignore null values in JSON response Jackson?

To ignore Null fields in JSON, Jackson provides Include. NON_NULL and to ignore Empty fields Jackson provides Include. NON_EMPTY .

Does Jackson use Java serialization?

This short tutorial shows how the Jackson library can be used to serialize Java object to XML and deserialize them back to objects.


2 Answers

Since someone asked this question again a few minutes ago, I did some research and think I found a good solution to this problem (when dealing with Strings).

You have to create a custom JsonDeserializer class as follows:

class NullStringJsonDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String result = StringDeserializer.instance.deserialize(p, ctxt);
        return result!=null && result.toLowerCase().equals(null+"") ? null : result;
    }
}

Last but not least, all you have to do is tell your ObjectMapper that it should use your custom json string deserializer. This depends on how and where you use your ObjectMapper but could look like that:

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new NullStringJsonDeserializer());
objectMapper.registerModule(module);
like image 197
FlorianDe Avatar answered Sep 28 '22 20:09

FlorianDe


If you use a custom Deserializer, you can do this, but I don't think it's available using standard annotations.

Borrowing and modifying some code from http://www.baeldung.com/jackson-deserialization :

public class ItemDeserializer extends JsonDeserializer<Item> {

    @Override
    public Item deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        String title = null;
        TextNode titleNode = (TextNode)node.get("title");
        if ( ! titleNode.toString().equals("null")) {
            title = titleNode.toString();
        }

        Date expires = null;
        // similar logic for expires

        return new Item(title, expires);
    }
}
like image 26
Dathan Avatar answered Sep 28 '22 19:09

Dathan