Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson: serialize non-initialized collection field as empty

I have a POJO with a field or property, containing collection of objects, something like this:

public class Box {

    public List<Items> items;

}

By default, value of items is null, and I do not want to initialize it with empty list.

Now, if I try to serialize it with Jackson, I get NullPointerException. Is there a simple way to make Jackson not break on such value and serialize it as an empty collection: [ ]?

Note. This class is just a simplified example. In reality, there are a hundred of classes and a number of fields with different names in each of them, which are occasionally set to null sometimes somewhere in the code, breaking serialization in runtime.

like image 633
Mikhail Batcer Avatar asked Sep 02 '25 10:09

Mikhail Batcer


2 Answers

If you do not want to change the contract of your POJO class, think about the possibility to define custom Jackson serializer / deserializer which extend JsonSerializer<T> and JsonDeserializer<T> respectively. E.g.:

 public class CountryDeserializer extends JsonDeserializer<CountryCode> {
     @Override
     public CountryCode deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
         return CountryCode.getByCode(jp.getText());
     }
 }

and then

 @JsonDeserialize(using=CountryDeserializer.class)
 private CountryCode country;

You can check whether your field is null and act accordingly, in both directions (serialization / deserialization).

like image 197
m c Avatar answered Sep 04 '25 00:09

m c


Have you considered making this class a JavaBean? In that case, you would be able to give a default value in the getter:

public class Box {
    private List<Items> items;
    public List<Items> getItems() {
        if(null == items) {
            return Collections.emptyList();
        }
        return this.items;
    }
    //Setter here
}

This approach would prevent a lot of trouble related to Jackson's assumptions.

Update: Based on clarification... You could implement a custom serializer for the list type (and/or any other desired customization). Please note that :

public class ListSerializer extends JsonSerializer<List> {
    @Override
    public void serialize(List value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
            JsonProcessingException {

        if (null == value) {
            provider.defaultSerializeValue(new ArrayList<Object>(), jgen);
        } else {
            provider.defaultSerializeValue(value, jgen);
        }
    }
}

//Then your code could set the serializer on the object mapper as follows:
objectMapper.addSerializer(List.class, new ListSerializer());

Repeat for all such customization.

Code was inspired by this article: http://www.baeldung.com/jackson-custom-serialization

like image 37
ernest_k Avatar answered Sep 03 '25 23:09

ernest_k