杰克逊:将非初始化的集合字段序列化为空

时间:2016-02-16 12:04:05

标签: java json serialization nullpointerexception jackson

我有一个带有字段或属性的POJO,包含对象集合,如下所示:

public class Box {

    public List<Items> items;

}

默认情况下,items的值为null,我不想使用空列表初始化它。

现在,如果我尝试用Jackson序列化它,我会得到NullPointerException。有没有一种简单的方法可以让杰克逊不打破这种价值并将其序列化为空集合:[ ]

注意。这个类只是一个简化的例子。实际上,每个类中都有一百个类和一些具有不同名称的字段,有时会在代码中的某处设置为null,从而在运行时打破序列化。

3 个答案:

答案 0 :(得分:2)

解决此问题的最简单方法是在默认构造函数中初始化List:

public class Box {

    private List<Item> items;

    public Box() {
        items = new ArrayList<>();
    }

    public List<Item> getItems() {
        return items;
    }

    public setItems(List<Item> items) {
        this.items = items;
    }

    public void addItem(Item item) {
        items.add(item);
    }
}

答案 1 :(得分:1)

您是否考虑过将此类设为JavaBean? 在这种情况下,您可以在getter中提供默认值:

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

这种方法可以防止与杰克逊的假设相关的很多麻烦。

更新:基于澄清......您可以为列表类型(和/或任何其他所需的自定义)实现自定义序列化程序。请注意:

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

重复所有此类自定义。

Code受到了本文的启发:http://www.baeldung.com/jackson-custom-serialization

答案 2 :(得分:1)

如果您不想更改POJO类的合约,请考虑定义自定义Jackson序列化器/解串器的可能性,该序列化器/解串器扩展 JsonSerializer&lt; T&gt; JsonDeserializer&lt; T&gt; < / em>分别。 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());
     }
 }

然后

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

您可以检查您的字段是否为空,并在两个方向上进行相应的操作(序列化/反序列化)。