jackson为一个具有多态类型的字段定制解串器

更新:

我尝试在jackson源代码中调试并在方法中找出它

deserialize(JsonParser jp, DeserializationContext ctxt)

SettableBeanProperty.java

_valueTypeDeserializer不为null时,它将永远不会使用_valueDeserializer

这是一个正确的假设,TypeDeserializer应该比ValueDeserializer更合适吗?


我正在尝试使用@JsonDeserialize为具有多态类型的一个字段定义自定义反序列化器。 我可以单独使用@JsonDeserialize@JsonTypeInfo 。 但是当我一起使用它们时,似乎忽略了@JsonDeserialize注释。

这是我的类层次结构:

1. Definition.java

 @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 } 

2. FormDefinition.java

 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; } } 

3. DefinitionDeserializer.java

 public class DefinitionDeserializer extends JsonDeserializer { @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); } } 

运行示例主应用程序将引发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"]) 

似乎使用AsPropertyTypeDeserializer反序列化FormDefinition类的definition字段而不是带注释的反序列化程序DefinitionDeserializer

我认为这里棘手的部分是我想使用自定义反序列化器的字段也是Definition类型,它使用@JsonTypeInfo来解决多态问题。

有没有办法一起使用它们? 谢谢。

Jackson在选择使用哪个Deserializer之前处理@JsonTypeInfo ,可能是因为Deserializer的选择通常可能取决于类型。 但是,您可以像指定自定义反序列化器一样轻松地在每个字段的基础上禁用它 – 通过直接注释字段:

 @JsonDeserialize(using = DefinitionDeserializer.class) @JsonTypeInfo(use = JsonTypeInfo.Id.NONE) private Definition definition;