Java Jackson将空字段反序列化为POJO中的默认空列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Jackson将空字段反序列化为POJO中的默认空列表相关的知识,希望对你有一定的参考价值。
我有一个带有lombok注释的POJO,我的JSON通过Jackson反序列化,如下所示:
@Getter
@ToString
@NoArgsConstructor
@Builder
@AllArgsConstructor
@EqualsAndHashCode
@JsonIgnoreProperties(ignoreUnknown = true)
public class ResponsePOJO {
@JsonProperty("list-one")
private List<Object> list1 = Lists.newArrayList;
@JsonProperty("list-two")
private List<Object> list2 = Lists.newArrayList;
@JsonProperty("list-three")
private List<Object> list3 = Lists.newArrayList;
@JsonProperty("list-four")
private List<Object> list4 = Lists.newArrayList;
}
当jackson尝试反序列化仅存在list-one和list-two的响应时,我期望得到的POJO具有属性list3
和list4
作为默认值的空列表,但是它们被反序列化为null
。
确保所有属性都包含来自反序列化JSON的相应值或空列表(默认分配值)的缺失是什么?
---更新----直到我从Spring 1.3.5升级到1.4.2,这也不是问题,它也将我的Jackson版本从2.6.6升级到2.8.4
问题是你还要添加@Builder
。初始化程序将移动到构建器,因为您不希望两次运行代码。
lombok的最新版本(1.16.16+)具有@Stone.Default,您可以使用它来影响该行为。
您可以指示Jackson使用构建器,并使您的对象不可变。 Builder适用于不可变对象。
披露:我是一名lombok开发者。
龙目岛的@Builder
在这里不是一个直接的问题,因为杰克逊并没有将它用于反序列化。但是,Jackson正在使用带有args的非默认构造函数(如果可用)用于对象实例化。否则它使用非arg构造函数。当您在@AllArgsConstructor
上使用ResponsePOJO
时,Jackson会创建一个如下所示的构造函数:
public ResponsePOJO(List<Object> list1, List<Object> list2, List<Object> list3, List<Object> list4) {
this.list1 = list1;
this.list2 = list2;
this.list3 = list3;
this.list4 = list4;
}
当调用此构造函数时,将丢弃您的默认值,并为JSON中不存在的字段分配null
。
虽然@Builder
需要所有参数构造函数,但您没有多少方法可以解决此问题:
- 不使用
@Builder
并删除@AllArgsConstructor
- 有时您可能不需要任何这些,但这取决于您的情况 - 删除
@AllArgsConstructor
并创建自定义构建器,它不使用里面的所有参数构造函数,而是使用no-arg构造函数。 - 使用
@Builder
并创建与此类似的自定义所有参数构造函数:public ResponsePOJO(List<Object> list1, List<Object> list2, List<Object> list3, List<Object> list4) { this.list1 = list1 == null ? Lists.newArrayList() : list1; this.list2 = list2 == null ? Lists.newArrayList() : list2; this.list3 = list3 == null ? Lists.newArrayList() : list3; this.list4 = list4 == null ? Lists.newArrayList() : list4; }
在这里,Jackson仍会调用上面的所有参数构造函数,但是如果某些字段不存在或者存在并且为null(如果在某些情况下您可能期望空值,例如对无效的验证,则可能会对您的业务逻辑产生下游影响),它将总是分配空列表。
我遇到了类似的问题,使用Jackson(com.fasterxml.jackson)和Lombok的@Builder注释反序列化JSON对象。我能够通过在类中创建一个用@JsonPOJOBuilder注释的空类Builder类来解决这个问题,然后添加一个带有对空类的引用的@JsonDeserialize。你可以找到更多信息here
例如,
@Getter
@ToString
@NoArgsConstructor
@Builder
@AllArgsConstructor
@EqualsAndHashCode
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonDeserialize(builder = ResponsePOJO.TypeBuilder.class)
public class ResponsePOJO {
@JsonPOJOBuilder(withPrefix = "")
@JsonIgnoreProperties(ModelUtils.TYPE_INFO_PROPERTY)
public static class TypeBuilder{}//Empty builder class
//Needed just to apply annotations
//Lombok will fill it in later.
@JsonProperty("list-one")
private List<Object> list1 = Lists.newArrayList;
@JsonProperty("list-two")
private List<Object> list2 = Lists.newArrayList;
@JsonProperty("list-three")
private List<Object> list3 = Lists.newArrayList;
@JsonProperty("list-four")
private List<Object> list4 = Lists.newArrayList;
}
以上是关于Java Jackson将空字段反序列化为POJO中的默认空列表的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jackson XmlMapper 将 XML 反序列化为 POJO