当存在额外的 getter 时,杰克逊反序列化会导致列表字段中出现重复的值

问题描述 投票:0回答:1

当我们添加列表字段的额外 getter 时,我试图解决 Jackson 反序列化到对象导致列表字段具有重复类的问题。

这是课程

public class Wrapper {

    private List<String> values;

    public List<String> getAllValues() {
        if (values == null) {
            values = new ArrayList<>();
        }
        return values;
    }

    public void setValues(final List<String> values) {
        this.values = values;
    }

    public List<String> getValues() {
        return values;
    }

    public String toString() {
        return MoreObjects.toStringHelper(this).add("values", values).toString();
    }
}

我尝试反序列化的 json 是这样的:

{
    "values": [
        "value1"
    ],
    "allValues": [
        "value1"
    ]
}

现在,根据我的理解,setter 仅适用于

values
,因此我希望 JSON 中的
allValues
条目被忽略,因为我那里没有任何 setter。它只是出于转换原因而引入的 getter 字段。

但显然,杰克逊并没有忽略该字段,而是利用它将其设置在

values
列表中。

下面是反序列化过程中确认重复条目的代码:

public static void main(String[] args) throws Exception {

    final ObjectMapper mapper = new ObjectMapper();

    final String wrapperJson = "{ \"values\": [ \"value1\" ], \"allValues\": [\"value1\"] }";

    System.out.println(mapper.readValue(wrapperJson.getBytes(), Wrapper.class));
}

打印的输出是这样的:

Wrapper{values=[value1, value1]}

有人可以解释杰克逊是如何创建重复条目的吗?

其他信息 - 我们正在使用 Jackson Databind - 2.13.5(是的,这是一个旧版本,所以新版本可能已经修复了这个问题)

java json jackson jackson-databind
1个回答
0
投票

你的字段之所以要序列化和反序列化两次,是因为 Jackson 的序列化和反序列化规则。 Jackson 使用 getter 进行序列化和反序列化,而如果缺少 getter,则 setter 仅用于反序列化。这是来自 Baeldung 的一篇关于序列化和反序列化规则的精彩文章。

在你的例子中,由于你有两个 getter 基本上返回相同的属性(

values
),所以这会被序列化两次。另一方面,在反序列化过程中,由于 Jackson 在这个实例中也使用了 getter,并且知道
values
getAllValues()
getValues()
getValues(), the first Json element is set via reflection by referring the attribute returned by 
getAllValues()
, while the second Json element is set via reflection by referring the attribute returned by 
values`都会返回
, which is still 

为了避免这种双重序列化/反序列化,您应该在两个 getter 之一之前添加

@JsonIgnore
注释,例如
getAllValues()

© www.soinside.com 2019 - 2024. All rights reserved.