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 中写问题的调试鸭子欢呼
我有这个例子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 中写问题的调试鸭子欢呼