为什么 Jackson 要将相同的 JSON 键/值写入两次?

Dav*_*ert 2 java json jackson

我对杰克逊有以下设置:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type")
@JsonSubTypes({
    @Type(value = Sub1.class, name = "sub1"),
    @Type(value = Sub2.class, name = "sub2")
})
abstract class BaseClass {
    private String type;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,Sub1 看起来像这样:

public class Sub1 extends BaseClass {
    String other;

    public String getOther() {
        return other;
    }

    public void setOther(String o) {
        other = o;
    }
}
Run Code Online (Sandbox Code Playgroud)

该设置基本上是为了允许解析包含不同类型嵌入元素的 json 文档。解析有效,但是当我想写出 Sub1 实例时,奇怪的是,“type”键被写入生成的 JSON 中两次:

ObjectMapper mapper = new ObjectMapper();
Sub1 d = new Sub1();
d.setType("sub1");

mapper.writerFor(Sub1.class).writeValue(System.out, d);
Run Code Online (Sandbox Code Playgroud)

我得到的输出是: {"type":"sub1","type":"sub1","other":null}

经过一番实验后,“类型”条目之一似乎是由

@Type(value = Sub1.class, name = "sub1")
Run Code Online (Sandbox Code Playgroud)

而另一个来自“type”属性。显然我只需要 JSON 中的“类型”条目。有谁知道如何防止这种情况,或者我做错了什么?

lea*_*ode 5

我有类似的问题。似乎有效的修复方法是使用

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.EXISTING_PROPERTY,
    property = "type")
Run Code Online (Sandbox Code Playgroud)

相反,即使用includeof JsonTypeInfo.As.EXISTING_PROPERTY。这使得 Jackson 使用AsExistingPropertyTypeSerializer,如果您跟踪Jackson 代码中的TypeSerializer#typeId(Object value, JsonToken valueShape) ,您将看到这使得序列化器期望该属性可用作常规 POJO属性,因为在本例中它使用WritableTypId.Inclusion.PAYLOAD_PROPERTY 。