简体   繁体   English

无法按照 Javadoc 中的描述使用 @JsonCreator 正确反序列化 JSON

[英]Can't properly deserialize JSON using @JsonCreator as described in the Javadoc

I've got a hard time understanding how Jackson's @JsonCreator annotation works (esp. with the different modes).我很难理解 Jackson 的@JsonCreator注释是如何工作的(尤其是在不同的模式下)。

I tried to simplify at most:我最多尝试简化:

public class JacksonDeserialization {

    private ObjectMapper om = new ObjectMapper();

    @Test // 1
    public void test_deserialization_emptyJson() throws JsonParseException, JsonMappingException, IOException {
        Wrapper read = om.readValue("{}", Wrapper.class);
        // Throws here: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `Inner` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)

        assertThat(read).isNotNull();
        assertThat(read.getInner()).isNull();
    }

    @Test // 2
    public void test_deserialization_innerIsEmpty() throws JsonParseException, JsonMappingException, IOException {
        Wrapper read = om.readValue("{\"inner\":{}}", Wrapper.class);
        // Throws here: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "inner" (class Inner), not marked as ignorable (one known property: "prop"])

        assertThat(read).isNotNull();
        assertThat(read.getInner()).isNotNull();
    }

    @Test // 3
    public void test_deserialization_innerIsSet() throws JsonParseException, JsonMappingException, IOException {
        Wrapper read = om.readValue("{\"inner\":{\"prop\":\"42\"}}", Wrapper.class);
        // Throws here: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "inner" (class Inner), not marked as ignorable (one known property: "prop"])

        assertThat(read).isNotNull();
        assertThat(read.getInner()).isNotNull();
        assertThat(read.getInner().getProp()).isEqualTo("42");
    }

}

My object classes:我的对象类:

public class Wrapper {

    private Inner inner;

    @JsonCreator
    public Wrapper(Inner inner) {
        this.inner = inner;
    }

    public Inner getInner() {
        return inner;
    }

}

and

public class Inner {

    private String prop;

    @JsonCreator
    public Inner(String prop) {
        this.prop = prop;
    }

    public String getProp() {
        return prop;
    }

}

Excerpts, from @JsonCreator Javadoc:摘录,来自@JsonCreator Javadoc:

NOTE: when annotating creator methods (constructors, factory methods),method must either be:注意:在注释创建者方法(构造函数、工厂方法)时,方法必须是:

•Single-argument constructor/factory method without JsonPropertyannotation for the argument: if so, this is so-called "delegate creator",in which case Jackson first binds JSON into type of the argument, andthen calls creator. • 单参数构造函数/工厂方法,参数没有JsonPropertyannotation:如果是这样,这就是所谓的“委托创建者”,在这种情况下,Jackson 首先将JSON 绑定到参数的类型,然后调用creator。 This is often used in conjunction with JsonValue(used for serialization).这通常与 JsonValue(用于序列化)结合使用。

...and from its mode argument: ...从它的mode参数:

Default value of Mode.DEFAULT means that caller is to use standardheuristics for choosing mode to use. Mode.DEFAULT 的默认值意味着调用者将使用标准启发式方法来选择要使用的模式。

com.fasterxml.jackson.annotation.JsonCreator.Mode.DEFAULT Javadoc: com.fasterxml.jackson.annotation.JsonCreator.Mode.DEFAULT Javadoc:

Pseudo-mode that indicates that caller is to use default heuristics for choosing mode to use.指示调用者将使用默认启发式方法来选择要使用的模式的伪模式。 This typically favors use of delegating mode for single-argument creators that take structured types.这通常有利于对采用结构化类型的单参数创建者使用委托模式。

What did I do wrong regarding these explanations?关于这些解释,我做错了什么?

I use Jackson 2.9.9.20190807 as indicated by one pom.xml from Spring Boot we're using.我使用 Jackson 2.9.9.20190807,如我们正在使用的 Spring Boot 中的一个 pom.xml 所示。

I admit I am not knowledgeable of JsonCreator modes.我承认我不了解 JsonCreator 模式。 However, the tests pass if you annotate the constructors arguments with property names.但是,如果您使用属性名称注释构造函数参数,则测试通过。

The rationale is that argument names is an optional compiler settings, so it is possible that Jackson is unable to read argument name through reflection and hence is unable to assign a deserialized value to that argument基本原理是参数名称是一个可选的编译器设置,因此 Jackson 可能无法通过反射读取参数名称,因此无法为该参数分配反序列化值

public class Wrapper {

    private Inner inner;

    @JsonCreator
    public Wrapper(@JsonProperty("inner") Inner inner) {
        this.inner = inner;
    }

    public Inner getInner() {
        return inner;
    }

}

public class Inner {

    private String prop;

    public Inner(@JsonProperty("prop") String prop) {
        this.prop = prop;
    }

    public String getProp() {
        return prop;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM