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

xi.*_*lin 21 java polymorphism json jackson deserialization

更新:

我尝试在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
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

3. DefinitionDeserializer.java

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

样品主要

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

运行示例主应用程序将引发异常:

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"])
Run Code Online (Sandbox Code Playgroud)

这似乎AsPropertyTypeDeserializer用于反序列definitionFormDefinition类的字段而不是带注释的反序列化器DefinitionDeserializer.

我觉得这里的棘手的部分是,我想使用自定义解串器领域也是类型Definition,其使用@JsonTypeInfo,解决了多态的问题.

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

Ant*_*jev 8

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

@JsonDeserialize(using = DefinitionDeserializer.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
private Definition definition;
Run Code Online (Sandbox Code Playgroud)