当前位置: 首页 > 知识库问答 >
问题:

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

秦阳旭
2023-03-14

我有一个带有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试图反序列化仅列出一个响应时

缺少什么来确保所有属性要么包含反序列化JSON中的相应值,要么包含默认分配值的空列表?

-更新-这不是问题,直到我从Spring 1.3.5升级到1.4.2,这也将我的Jackson版本从2.6.6升级到2.8.4

共有3个答案

班展
2023-03-14

我在使用Jackson (com.fasterxml.jackson)和Lombok的@Builder注释反序列化JSON对象时遇到了类似的问题。我可以通过在类中创建一个用@ JsonPOJOBuilder注释的空构建器类,然后添加一个引用空类的@JsonDeserialize来解决这个问题。你可以在这里找到更多信息

例如

@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;
}
左丘嘉言
2023-03-14

问题是你也添加了@Builder。初始值设定项将移动到生成器,因为您不希望运行代码两次。

lombok的最新版本(1.16.16)具有@Builder.Default,您可以使用它来影响该行为。

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

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

胡鸿羲
2023-03-14

龙目岛的@Builder在这里不是一个直接的问题,因为杰克逊不用它来反序列化。但是,Jackson 使用带有 args 的非默认构造函数(如果可用)进行对象实例化。否则,它将使用非 arg 构造html" target="_blank">函数。当您在响应POJO上使用@AllArgsConstructor时,杰克逊采用创建的构造函数,如下所示:

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并创建自定义生成器,该生成器不是使用内部的所有参数构造函数,而是使用无参数构造函数。
  • 使用@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仍然会调用上面的所有参数构造函数,但是如果某些字段不存在或存在并且是空的(如果在某些情况下您可能期望空值,例如针对空性的验证),这可能会对您的业务逻辑产生下游影响),它将始终分配空列表。

  •  类似资料:
    • 我有一个JSON字符串,它将空列表标记为而不是。因此,例如,如果我有一个没有子对象的对象,我将收到这样的字符串: 我想将其反序列化为父类,将子类正确设置为子类的空列表。 对于上面的JSON字符串,我想要一个将其id设置为13的对象,并将子元素设置为新的ArrayList 我知道如何为整个类使用注释 然后呢 但是,我想解决从字符串正确实例化列表的一般问题: 我能得到这样的东西吗?

    • 问题内容: 我有以下类,它是由Jackson映射的(简化版): 在某些情况下,服务器会返回,然后我想将name设置为空的Java String。 是否有任何Jackson注释,或者如果属性为,我应该只检查getter中的null并返回空字符串? 问题答案: 您可以在默认构造函数中或声明时进行设置: 要么

    • 我有以下由Jackson映射的类(简化版): 在某些情况下,服务器返回,然后我想将name设置为空Java字符串。 是否有任何Jackson注释,或者如果属性为,我应该只检查getter中的null并返回空字符串吗?

    • 问题内容: 是否可以通过SQL语句确保列的默认值为空字符串而不是? 问题答案: 是-使用DEFAULT约束:

    • 我重构我的代码来使用kryo序列化。一切都很好,除了从某个类中反序列化一个土工属性。不会引发异常(我将“spark.kryo.registrationRequired”设置为true)。在调试时,我试图收集数据,但我看到geomtry中的数据只是空的。结果,我明白反序列化失败了。Geomtry来自-Any(scala)类型,因为它可能是一个复杂的属性。我的问题是为什么数据是空的,以及是否与属性的类

    • 我有通过WCF(servicecontract接口、dataContracts等)从服务器检索数据应用程序 我有对象: 我将DataRow中字典填充为(列名)-->(列中的值) DataRow中的某些单元格可以为空。字典中具有所有非空值的对象将正确地序列化和反序列化。但如果值为null,则服务只需停止序列化而不会出现任何错误。它并没有停止工作:我的应用程序仍然试图将请求重复到service,而我在