[英]Jackson custom deserializer for one field with polymorphic types
Update: 更新:
I tried to debug in jackson source code and find out that in the method 我尝试在jackson源代码中调试并在方法中找出它
deserialize(JsonParser jp, DeserializationContext ctxt)
of deserialize(JsonParser jp, DeserializationContext ctxt)
SettableBeanProperty.java
when the _valueTypeDeserializer
isn't null, it will never use _valueDeserializer
. 当
_valueTypeDeserializer
不为null时,它将永远不会使用_valueDeserializer
。
Is this a correct assumption that TypeDeserializer should be more proper than ValueDeserializer? 这是一个正确的假设,TypeDeserializer应该比ValueDeserializer更合适吗?
I'm trying to use @JsonDeserialize
to define custom deserializer for one field with polymorphic types. 我正在尝试使用
@JsonDeserialize
为一个具有多态类型的字段定义自定义反序列化器。 I can succeed to use @JsonDeserialize
and @JsonTypeInfo
seperately. 我可以单独使用
@JsonDeserialize
和@JsonTypeInfo
。 But when i use them together, it seems that the @JsonDeserialize
annotation is ignored. 但是当我一起使用它们时,似乎忽略了
@JsonDeserialize
注释。
Here is my class hierarchy: 这是我的类层次结构:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", defaultImpl = Definition.class)
@JsonSubTypes({@Type(value = Definition.class, name = "normal"),
@Type(value = FormDefinition.class, name = "form")})
public class Definition {
private String name;
private String description;
// getter&setter for name&description
}
public class FormDefinition extends Definition {
private String formName;
@JsonDeserialize(using = DefinitionDeserializer.class)
private Definition definition;
public String getFormName() {
return formName;
}
public void setFormName(String formName) {
this.formName = formName;
}
public void setDefinition(Definition definition) {
this.definition = definition;
}
}
public class DefinitionDeserializer extends JsonDeserializer<Definition> {
@Override
public Definition deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
Definition definition = new Definition();
String name = jsonParser.readValueAs(String.class);
definition.setName(name);
return definition;
}
}
public class App
{
public static void main( String[] args ) throws IOException {
String sampleData = "{\"type\":\"form\",\"definition\":\"super\",\"formName\":\"FormName\"}";
ObjectMapper mapper = new ObjectMapper();
Definition definition = mapper.readValue(sampleData, Definition.class);
System.out.println(definition);
}
}
Running the sample main app will throw an exception: 运行示例主应用程序将引发异常:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class jp.co.worksap.model.Definition] from String value ('super'); no single-String constructor/factory method (through reference chain: jp.co.worksap.model.FormDefinition["definition"])
which seems using AsPropertyTypeDeserializer
to deserialize the definition
field of FormDefinition
class instead of the annotated deserializer DefinitionDeserializer
. 它似乎使用
AsPropertyTypeDeserializer
来反序列化FormDefinition
类的definition
字段而不是带注释的反序列化程序DefinitionDeserializer
。
I think the tricky part here is that the field I want to use custom deserializer is also type of Definition
which using @JsonTypeInfo
to solve the polymorphic problems. 我认为这里棘手的部分是我想使用自定义反序列化器的字段也是
Definition
类型,它使用@JsonTypeInfo
来解决多态问题。
Is there any way to use them together? 有没有办法一起使用它们? Thanks.
谢谢。
Jackson processes @JsonTypeInfo
before choosing which Deserializer to use, probably because the choice of Deserializer could depend generally on the type. Jackson在选择使用哪个Deserializer之前处理
@JsonTypeInfo
,可能是因为Deserializer的选择通常可能取决于类型。 However, you can easily disable this on a per-field basis the same way you specify custom Deserializer - by annotating the field directly: 但是,您可以像指定自定义反序列化器一样轻松地在每个字段的基础上禁用它 - 通过直接注释字段:
@JsonDeserialize(using = DefinitionDeserializer.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
private Definition definition;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.