Jackson:反序列化包含列表的泛型类型

时间:2014-10-16 17:18:36

标签: java json jackson

我希望从JSON反序列化的实体如下:

public class TypedMemberDTO<T> {

        private List<T> details;
        private String type;

        // Getters and setters
    }

我知道T可能只是两个实际类别中的一个,具体取决于type属性的值。

我已经看过如何使用objectMapper.readValue(json, objectMapper.getTypeFactory().collectionType(ArrayList.class, MyClass.class));

反序列化列表的示例

但是,我还没有看到任何关于如何实现我上面要做的事情的例子。

有人可以在反序列化我的课程时指出正确的方向吗?

理想情况下,如果可能的话,我想避免任何基于注释的方法

1 个答案:

答案 0 :(得分:3)

正如@fge在评论中建议的那样,您可以使用自定义反序列化器来实现此目的。

假设type包含列表元素的完全限定类名,以下反序列化器将完成这项工作:

public class TypedMemberDTODeserializer extends JsonDeserializer<TypedMemberDTO<?>> {

    @Override
    public TypedMemberDTO<?> deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException {
        try {
            JsonNode rootNode = jp.getCodec().readTree(jp);
            String type = rootNode.get("type").asText();
            JavaType parametricListType = ctxt.getTypeFactory().constructParametricType(
                    List.class, Class.forName(type));
            JsonNode detailsNode = rootNode.get("details");
            List<?> detailsList = new ObjectMapper().readValue(detailsNode.toString(), parametricListType);
            return new TypedMemberDTO(detailsList, type); // unchecked
        } catch (ClassNotFoundException e) {
            throw new IOException(e);
        }

    }
}

ObjectMapper需要了解解串器:

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new SimpleModule().addDeserializer(TypedMemberDTO.class,
                new TypedMemberDTODeserializer()));
        TypedMemberDTO<?> typedMemberDTO = objectMapper.readValue(jsonString, TypedMemberDTO.class);

我不知道此解决方案的性能(它在反序列化程序中使用嵌入式ObjectMapper),您可能需要检查它。您可以阅读有关自定义反序列化程序here的更多信息。