Java Jackson 自定义反序列化器,用于具有多态类型的一个字段

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27351698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 04:12:38  来源:igfitidea点击:

Hymanson custom deserializer for one field with polymorphic types

javajsonpolymorphismHymansondeserialization

提问by xi.lin

Update:

更新:

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

我尝试在 Hymanson 源代码中调试并在方法中发现

deserialize(JsonParser jp, DeserializationContext ctxt)of

deserialize(JsonParser jp, DeserializationContext ctxt)

SettableBeanProperty.java

SettableBeanProperty.java

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

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

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

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



I'm trying to use @JsonDeserializeto define custom deserializer for one field with polymorphic types. I can succeed to use @JsonDeserializeand @JsonTypeInfoseperately. But when i use them together, it seems that the @JsonDeserializeannotation is ignored.

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

Here is my class hierarchy:

这是我的类层次结构:

1. Definition.java

1.定义.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

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.定义Deserializer.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.Hymanson.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 AsPropertyTypeDeserializerto deserialize the definitionfield of FormDefinitionclass instead of the annotated deserializer DefinitionDeserializer.

这似乎AsPropertyTypeDeserializer用于反序列definitionFormDefinitionclass的字段而不是带注释的 deserializer DefinitionDeserializer

I think the tricky part here is that the field I want to use custom deserializer is also type of Definitionwhich using @JsonTypeInfoto solve the polymorphic problems.

我觉得这里最棘手的部分是外地我想使用自定义解串器也键入Definition其使用@JsonTypeInfo,解决了多态的问题。

Is there any way to use them together? Thanks.

有什么办法可以一起使用吗?谢谢。

回答by Anton Koscejev

Hymanson processes @JsonTypeInfobefore 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:

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

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