杰克逊动态Pojo <t> Deseralization

时间:2017-06-12 16:06:01

标签: java json spring jackson

拥有像下一个一样的动态POJO:

@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyDynamicWrapper <T> {

    @JsonProperty("header")
    private CommonHeader header;

    @JsonProperty("payload")
    private T payload;

    public MyDynamicWrapper(CommonHeader header, T payload) {
        super();
        this.header = header;
        this.payload = payload;
    }

    public CommonHeader getHeader() {
        return header;
    }

    public void setHeader(CommonHeader header) {
        this.header = header;
    }

    public T getPayload() {
        return payload;
    }

    public void setPayload(T payload) {
        this.payload = payload;
    }
}

T有效负载可以是以下之一:

@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyPayloadOne {

    @JsonProperty("status")
    private int status; 

    @JsonProperty("action")
    private String action;  

    ...
}

@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyPayloadTwo {

    @JsonProperty("properties")
    private List<String> properties = new ArrayList<>();    

    ...
}

杰克逊对这些动态信息进行反序列化的最佳方法是什么?是否必须实现反序列化器?我当前的配置不是动态的,我正在使用:

MyDynamicWrapper pojo = jacksonMapper.readValue(jsonMessage, MyDynamicWrapper.class);

我认为这是如此明显,但我不知道如何表明杰克逊的动态参考。

更新

除了接受的答案,我还检查过可以像这样定义杰克逊映射器:

MyDynamicWrapper<?> pojo = jacksonMapper.readValue(jsonMessage, MyDynamicWrapper.class);

这会将POJO转换为两个有效负载。

4 个答案:

答案 0 :(得分:1)

You can (and should) pass a TypeReference to readValue to specify the type of generic class instance you want to deserialize. E.g. when wrapping MyPayloadOne:

TypeReference ref = new TypeReference<MyDynamicWrapper<MyPayloadOne>>(){};
MyDynamicWrapper<MyPayloadOne> pojo = jacksonMapper.readValue(jsonMessage, ref);

答案 1 :(得分:0)

您需要通过实施this类来编写自定义序列化程序。或Deserializer

答案 2 :(得分:0)

尝试使用此问题中指定的@JsonCreator和@JsonProperty。 Is Jackson really unable to deserialize json into a generic type?

杰克逊需要更多的帮助来确定要反序列化的类型,这就是那些注释有助于做的事情。

答案 3 :(得分:0)

如果您在编译时知道类型参数,那么您可以使用TypeReference反序列化JSON,如接受的答案中所述。
如果在编译时未知类型参数,那么即使这样也可以反序列化JSON。要实现这一点,您需要在可以作为类型参数传递给通用MyDynamicWrapper<T>的所有类上放置某些Jackson注释。

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName("MyPayloadOne")
public class MyPayloadOne {

}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName("MyPayloadTwo ")
public class MyPayloadTwo {

}

现在,当您将使用MyDynamicWrapperMyPayloadOne创建的MyPayloadTwo实例反序列化为参数时,Jackson会将类型参数信息放入JSON中。然后可以将此JSON反序列化为泛型类MyDynamicWrapper.class,就像反序列化任何其他类一样,即, 无需指定类型参数(MyPayloadOneMyPayloadTwo)。

MyDynamicWrapper<?> pojo = jacksonMapper.readValue(jsonString, MyDynamicWrapper.class);

请参阅Polymorphic DeserializationAnnotations上的杰克逊文档。