使用 Jackson 对 JSON 字段进行自定义反序列化
Custom deserialisation of JSON field using Jackson
我正在使用 Jackson 反序列化某些 JSON,但我 运行 在尝试对其中一个字段使用自定义反序列化程序时遇到了一些麻烦。
class MyClass
{
private static class SpecialPropertyDeserializer extends JsonDeserializer<SpecialProperty>
{
@Override
public SpecialProperty deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException, JsonProcessingException
{
// do some custom deserialisation
}
}
private static class SpecialProperty
{
private String m_foo;
private String m_bar;
@JsonCreator
SpecialProperty(@JsonProperty("foo") String foo,
@JsonProperty("bar") String bar)
{
m_foo = foo;
m_bar = bar;
}
}
private String m_identifier;
private String m_version;
@JsonDeserialize(using = SpecialPropertyDeseializer.class)
private SpecialProperty m_specialProperty;
@JsonCreator
MyClass(@JsonProperty("identifier") String identifier,
@JsonProperty("version") String version,
@JsonProperty("specialProperty") SpecialProperty specialProperty)
{
m_identifier = identifier;
m_version = version;
m_specialProperty = specialProperty;
}
}
这是我要反序列化的JSON:
{
"identifier" : "some-id",
"version" : "1.7",
"specialProperty" : {
"foo" : "str1",
"bar" : "str2"
},
}
我调用映射器如下:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
return objectMapper.readValue(input, MyClass.class);
我观察到以下行为:
- 没有特殊的 属性 一切正常 - 即删除所有
从代码和 JSON.
中引用 SpecialProperty
- 如果我在 JSON 中包含
SpecialProperty
但删除自定义
它的反序列化器然后它也可以正常工作。的ctor
SpecialProperty
被调用。
- 自定义解串器不起作用。调用了
SpecialProperty
的构造函数,但未调用自定义反序列化器。
我做错了什么?
@JsonDeserialize
注释可以放在字段上,setter 或 class。如果注释的是它用来设置值的内容,杰克逊将考虑它。
E.g.1 如果它使用 setter 来设置字段的值,它会注意到 @JsonDeserialize
而不是 setter。
E.g.2 如果不使用 setter 或构造函数直接设置该字段,它将注意到该字段 @JsonDeserialize
。
如果它在 class 上,它将倾向于考虑它,除非它被字段上更具体的注释或 setter docs 覆盖。我认为文档在上述细节上可能会更清楚。
在你的例子中,你在 SpecialProperty
字段上有注释,但你在 MyClass
构造函数中设置了这个字段,所以它被忽略了。
在这种情况下,您可以将 @JsonDeserialize
移动到 class 上,而不是移动到字段上。在您的情况下,这可能是最简单的解决方案。例如
@JsonDeserialize(using = MyClass.SpecialPropertyDeserializer.class)
private static class SpecialProperty {
或者您可以完全跳过注释并在映射器上注册反序列化器。首先在 MyClass
中使 SpecialProperty
和 SpecialPropertyDeserializer
非私有,然后:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(MyClass.SpecialProperty.class, new MyClass.SpecialPropertyDeserializer());
objectMapper.registerModule(module);
您也可以删除 MyClass
的构造函数,并且将考虑 SpecialProperty
字段上的当前注释。
我正在使用 Jackson 反序列化某些 JSON,但我 运行 在尝试对其中一个字段使用自定义反序列化程序时遇到了一些麻烦。
class MyClass
{
private static class SpecialPropertyDeserializer extends JsonDeserializer<SpecialProperty>
{
@Override
public SpecialProperty deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException, JsonProcessingException
{
// do some custom deserialisation
}
}
private static class SpecialProperty
{
private String m_foo;
private String m_bar;
@JsonCreator
SpecialProperty(@JsonProperty("foo") String foo,
@JsonProperty("bar") String bar)
{
m_foo = foo;
m_bar = bar;
}
}
private String m_identifier;
private String m_version;
@JsonDeserialize(using = SpecialPropertyDeseializer.class)
private SpecialProperty m_specialProperty;
@JsonCreator
MyClass(@JsonProperty("identifier") String identifier,
@JsonProperty("version") String version,
@JsonProperty("specialProperty") SpecialProperty specialProperty)
{
m_identifier = identifier;
m_version = version;
m_specialProperty = specialProperty;
}
}
这是我要反序列化的JSON:
{
"identifier" : "some-id",
"version" : "1.7",
"specialProperty" : {
"foo" : "str1",
"bar" : "str2"
},
}
我调用映射器如下:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
return objectMapper.readValue(input, MyClass.class);
我观察到以下行为:
- 没有特殊的 属性 一切正常 - 即删除所有 从代码和 JSON. 中引用
- 如果我在 JSON 中包含
SpecialProperty
但删除自定义 它的反序列化器然后它也可以正常工作。的ctorSpecialProperty
被调用。 - 自定义解串器不起作用。调用了
SpecialProperty
的构造函数,但未调用自定义反序列化器。
SpecialProperty
我做错了什么?
@JsonDeserialize
注释可以放在字段上,setter 或 class。如果注释的是它用来设置值的内容,杰克逊将考虑它。
E.g.1 如果它使用 setter 来设置字段的值,它会注意到 @JsonDeserialize
而不是 setter。
E.g.2 如果不使用 setter 或构造函数直接设置该字段,它将注意到该字段 @JsonDeserialize
。
如果它在 class 上,它将倾向于考虑它,除非它被字段上更具体的注释或 setter docs 覆盖。我认为文档在上述细节上可能会更清楚。
在你的例子中,你在 SpecialProperty
字段上有注释,但你在 MyClass
构造函数中设置了这个字段,所以它被忽略了。
在这种情况下,您可以将 @JsonDeserialize
移动到 class 上,而不是移动到字段上。在您的情况下,这可能是最简单的解决方案。例如
@JsonDeserialize(using = MyClass.SpecialPropertyDeserializer.class)
private static class SpecialProperty {
或者您可以完全跳过注释并在映射器上注册反序列化器。首先在 MyClass
中使 SpecialProperty
和 SpecialPropertyDeserializer
非私有,然后:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(MyClass.SpecialProperty.class, new MyClass.SpecialPropertyDeserializer());
objectMapper.registerModule(module);
您也可以删除 MyClass
的构造函数,并且将考虑 SpecialProperty
字段上的当前注释。