【问题标题】:Jackson serialization outputting two json rows for one java variableJackson 序列化为一个 java 变量输出两个 json 行
【发布时间】:2020-08-14 21:32:01
【问题描述】:

当我将代码从 Java 8 和 Sprint Boot 1.X 迁移到 11 和 2.X 时,我遇到了一个奇怪的问题。之前,我发现 Jackson 正在将 private boolean isAvailable 序列化为 available: falseisAvailable: false。为了增加更多的混乱,龙目岛一直在路上,所以我看不到吸气剂,如果这会导致冲突。下面是Java类代码:

@Data
public class Availability{

    @JsonProperty("isAvailable")
    private boolean isAvailable;

}

Jackson 对象映射器生成的 JSON 是:

"Availability" : [{
          "isAvailable" : false,
          "available" : false }]

这是 Jackson 2.8。现在有了 Jackson 2.10,我只得到 isAvailable: false 作为 ObjectMapper 的 JSON 输出。

"Availability" : [{
          "isAvailable" : false }]

对我来说,它应该只匹配 Java 变量名是有道理的,但遗憾的是合同有两个版本,我不想更改合同。有些使用的是,有些不是。我知道自定义序列化程序是可能的,但不确定如何执行或是否有必要。

【问题讨论】:

    标签: java json jackson lombok


    【解决方案1】:

    是龙目岛+田野,互动。

    让我们参加这个假设的课程(没有龙目岛,或者杰克逊在这里涉及所有):

    class Example {
        public boolean isAvailable() {
            return true;
        }
    }
    

    根据 beanspec,Example 类有一个名为 available 的布尔类型的只读 bean 属性。这是因为任何返回布尔值并以is(然后是大写字母)开头的无参数方法都算作访问器,要获取它的名称,请去掉is .

    所以这是从那一端来看的。现在让我们从另一端来看它,您编写了一个类,无论出于何种原因,您决定将该字段命名为isAvailable。真正的问题是:您希望“属性”被命名为什么(根据 beanspec)?如果它真的被称为isAvailable,那么只有一种方法可以做到:

    class Example {
        public boolean isIsAvailable() {
            return true;
        }
    }
    

    是的,isIsAvailable。看起来很愚蠢,但是,如果您希望属性本身称为isAvailable,这就是规则所规定的。 Lombok 决定(来源:我是核心贡献者)当您在名为 isAvailable 的字段上粘贴 @Getter 注释时,没有人真正想要名为 isIsAvailable 的方法。

    所以,就杰克逊而言,现在你有一个实际上看起来像这样的类:

    class Availability {
        @JsonProperty("isAvailable") private boolean isAvailable;
    
        public boolean isAvailable() { return this.isAvailable; }
    }
    

    不使用特定的智能,仅应用字面规则,意味着杰克逊说:好的,这里有 2 个不同的属性,available(通过调用 isAvailable() 获得)和 @ 987654337@ 字段。对于 beanspec 样式的 getter,is/get 会被剥离,而对于字段则不会,尤其是如果您在其中粘贴 @JsonProperty("isAvailable")

    这就是为什么这一切发生的背景。

    一种解决方案可能是采用这种方法:

    @JsonProperty("available")
    public boolean getAvailable() { return this.available; }
    

    我认为这会让你在 JSON 输出中获得两种变体。

    【讨论】:

    • 感谢您的评论。处理遗留代码肯定是一件麻烦事,我了解 Java bean 规范以及 Jackson 和 Lombok 如何处理这个问题。我有点困惑,为什么当依赖项发生变化并且底层 pojo 没有改变时行为会发生变化。
    • 我会说通常不希望像这样同时获得 'available' 和 'isAvailable' ,所以大概杰克逊更新到相同的智能龙目岛适用。我们在 lombok 已经在这种奇特的情况下打破了几次向后兼容性,但并没有对此做出任何特别的解释(没有 v2.0 或诸如此类的东西),也许他们也这样做了?
    • 我会告诉你,以这种方式编写带有 json 属性的 getter 确实有效,但现在是与客户取得联系并更改合同的时候了。为什么以前没有人注意到这一点很糟糕。我讨厌继承代码,但软件世界中的生活有时就是这样!再次感谢,龙目岛是一个样板救生员顺便说一句。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 2017-12-24
    • 1970-01-01
    • 2018-07-14
    • 2016-09-10
    • 1970-01-01
    相关资源
    最近更新 更多