Java Jackson将空字段反序列化为POJO中的默认空列表

时间:2017-12-17 22:01:03

标签: java json jackson deserialization lombok

我有一个带有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;
}

当杰克逊试图反序列化只有列表1和1的响应时list-two存在,我希望生成的POJO具有属性list3list4作为空列表,这是默认值,而是将它们反序列化为null

确保所有属性都包含来自反序列化JSON的相应值或空列表(默认分配值)缺少什么?

--- ----更新 直到我从Spring 1.3.5升级到1.4.2之后才出现问题,这也将我的Jackson版本从2.6.6升级到2.8.4

3 个答案:

答案 0 :(得分:0)

问题是您还要添加@Builder。初始化程序将移动到构建器,因为您不想运行代码两次。

lombok的最新版本(1.16.16+)有@ Builder.Default可用于影响该行为。

您可以指示Jackson使用构建器,并使您的对象不可变。 Builder适用于不可变对象。

披露:我是一名lombok开发者。

答案 1 :(得分:0)

龙目岛的var userId = new Guid("96d5b379-7e1d-4dac-a6ba-1e50db561b04"); objDB.AddInParameter(objcmd, "@UserID", SqlDbType.UniqueIdentifier, userId); 在这里不是直接的问题,因为杰克逊并没有将它用于反序列化。但是,Jackson正在使用带有args的非默认构造函数(如果可用)用于对象实例化。否则它使用非arg构造函数。当您在@Builder上使用@AllArgsConstructor时,杰克逊会创建一个如下所示的构造函数:

ResponsePOJO

当调用此构造函数时,将丢弃您的默认值,并为JSON中不存在的字段分配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; }

虽然null需要所有参数构造函数,但您无法解决问题:

  1. 不使用@Builder并删除@Builder - 有时您可能不需要这些,但这取决于您的情况
  2. 删除@AllArgsConstructor并创建自定义构建器,该构建器不使用里面的所有参数构造函数,但是使用no-arg构造函数。
  3. 使用@AllArgsConstructor并创建与此类似的自定义所有参数构造函数:

    @Builder

    这里Jackson仍会调用上面的所有参数构造函数,但是如果某些字段不存在或者存在且为null(如果在某些情况下您可能期望空值,例如对无效的验证,则可能会对您的业务逻辑产生下游影响) ,它将始终分配空列表。

答案 2 :(得分:0)

我遇到了类似的问题,使用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;
}