java / jackson - 链接@JsonValue注释和反序列化

时间:2014-12-29 22:04:39

标签: java jackson deserialization

我有以下结构。我知道这看起来很奇怪,但我用这个例子来模拟我们的代码。

public static class StringWrapper {
    protected final String s;

    @JsonValue
    public String getS() {
        return s;
    }

    public StringWrapper(final String s) {
        this.s = s;
    }
}

public static class StringWrapperOuter {
    protected final StringWrapper s;

    @JsonValue
    public StringWrapper getS() {
        return s;
    }

    public StringWrapperOuter(final StringWrapper s) {
        this.s = s;
    }
}

public static class POJO {
    protected final List<StringWrapperOuter> data;

    public List<StringWrapperOuter> getData() {
        return data;
    }

    public POJO(final List<StringWrapperOuter> data) {
        this.data = data;
    }

    public POJO() {
        data = Collections.emptyList();
    }
}

pojo的序列化给出了预期的JSON字符串数组:

<mapper>.writeValue(System.out, new POJO(Arrays.asList(new StringWrapperOuter(new StringWrapper("a")), new StringWrapperOuter(new StringWrapper("b")), new StringWrapperOuter(new StringWrapper("c")))));

{"data":["a","b","c"]}

如何将此JSON字符串反序列化为POJO类型的对象?

<mapper>.readValue("{\"data\":[\"a\",\"b\",\"c\"]}", POJO.class);

映射器很难识别输入,因为两个@JsonValue注释是链接的。它给出了以下例外:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class StringWrapperOuter] from String value ('a'); no single-String constructor/factory method
 at [Source: {"data":["a","b","c"]}; line: 1, column: 10] (through reference chain: POJO["data"]->java.util.ArrayList[0])

2 个答案:

答案 0 :(得分:10)

@JsonValue用于序列化。反序列化的类似注释是@JsonCreator

注释构造函数

@JsonCreator
public StringWrapper(final String s) {
    this.s = s;
}

@JsonCreator
public StringWrapperOuter(final StringWrapper s) {
    this.s = s;
}

答案 1 :(得分:5)

Sotirios在之前的回答中说。 @JsonCreator是关键所在。但是,为了让所有课程都能运作@JsonProperty,可能需要。

public static class POJO {
    protected final List<StringWrapperOuter> data;

    // In order for POJO creation to work properly the @JsonProperty
    // annotation on the arg is required
    @JsonCreator
    public POJO(@JsonProperty("data") final List<StringWrapperOuter> data) {
        this.data = data;
    }

    public List<StringWrapperOuter> getData() {
        return data;
    }
}

public static class StringWrapper {
    protected final String s;

    @JsonCreator
    public StringWrapper(final String s) {
        this.s = s;
    }

    @JsonValue
    public String getS() {
        return s;
    }
}

public static class StringWrapperOuter {
    protected final StringWrapper s;

    @JsonCreator
    public StringWrapperOuter(final StringWrapper s) {
        this.s = s;
    }

    @JsonValue
    public StringWrapper getS() {
        return s;
    }
}