Jackson 映射器跳过 class 名称(反序列化问题)

Jackson mapper skip class name (deserialization issue)

我有这个例子class:

@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class ExampleClass implements Serializable {
    private String name;
    private String color;
}

这个 class 序列化为:

{
    "ExampleClass":{
        "name":"This is some name",
        "color":"This is some color"
}}

这是预期的行为,我不应该改变它。 但我首先收到的文件是这样 json:

{
    "name":"This is some name",
    "color":"This is some color"
}

我需要将它映射到我的 ExampleClass,通常你会像这样简单地做:

ExampleClass example = new ObjectMapper().readValue(jsonFile, ExampleClass.class);

但是因为我已经用注释指定了 class @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 它试图映射 "name" 字段收到的 json 到 "ExampleClass" 并抛出错误:

Could not resolve type id 'name' as a subtype of com.example.package.dto.ExampleClass: known type ids = [ExampleClass]

我知道如果我删除 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 或者我将其更改为 use = JsonTypeInfo.Id.NONE 反序列化将起作用,但随后序列化json 最终改变了,所以我不能那样做。

我还知道,如果我想添加一个自定义反序列化器,我还需要添加一个自定义序列化器,因为 @JsonTypeInfo 注释使 jackson 忽略您在注释中指定的任何反序列化器。但我真的想避免这种情况,因为实际的 class 有很多字段,自定义映射 classes 会看起来很丑。

我如何告诉 jackson 跳过 "ExampleClass" 字段并将其映射到它的内部字段,或者指定不同的字段?

我正在使用 fasterxml.jackson,没有 codehaus。

有趣的是,当我写下我的问题时,我想到了解决方案,只需要实施它并尝试一下,它最终完美地工作了!

我是这样做的:

@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
// no more @JsonTypeInfo here
public class ExampleClass implements Serializable {
    private String name;
    private String color;
}

我从 ExampleClass 中删除了 @JsonTypeInfo,因为这个 class 将用于反序列化接收到的 json。 然后我创建了第二个 "wrapper" class,我将使用它来序列化数据:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class ExampleClassWrapper extends ExampleClass {
    public ExampleClassWrapper(ExampleClass ex) {
        super(ex.getName(), ex.getColor());
    } 

现在当 json 出现时,我可以在一行中毫无错误地阅读它:

ExampleClass example = new ObjectMapper().readValue(jsonFile, ExampleClass.class);

当我需要序列化此数据时(例如将其作为请求发送),我只需发送 ExampleClassWrapper:

ExampleClassWrapper wrapper = new ExampleClassWrapper(example);
exampleRestService.sendExampleRequest(wrapper);

如果您认为有更好的解决方法,请随时指正。

P.S。为在 Whosebug 中写问题的调试鸭子欢呼