杰克逊为一个具有多态类型的字段定制解串器 [英] Jackson custom deserializer for one field with polymorphic types

查看:113
本文介绍了杰克逊为一个具有多态类型的字段定制解串器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:

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

I tried to debug in jackson source code and find out that in the method

反序列化(JsonParser jp,DeserializationContext ctxt) of

SettableBeanProperty.java

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

when the _valueTypeDeserializer isn't null, it will never use _valueDeserializer.

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

Is this a correct assumption that TypeDeserializer should be more proper than ValueDeserializer?

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

I'm trying to use @JsonDeserialize to define custom deserializer for one field with polymorphic types. I can succeed to use @JsonDeserialize and @JsonTypeInfo seperately. But when i use them together, it seems that the @JsonDeserialize annotation is ignored.

这是我的类层次结构:

@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



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



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



样本主



Sample main

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"])

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

which seems using AsPropertyTypeDeserializer to deserialize the definition field of FormDefinition class instead of the annotated deserializer DefinitionDeserializer.

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

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.

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

Is there any way to use them together? Thanks.

推荐答案

杰克逊在选择使用哪个解串器之前处理 @JsonTypeInfo ,可能是因为反序列化器的选择通常取决于类型。但是,您可以在每个字段的基础上轻松禁用此功能,方法与指定自定义反序列化器相同 - 通过直接注释字段:

Jackson processes @JsonTypeInfo before choosing which Deserializer to use, probably because the choice of Deserializer could depend generally on the type. 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;

这篇关于杰克逊为一个具有多态类型的字段定制解串器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆