Jackson 2 ObjectMapper
类定义了许多用于将JSON字符串,字节数组,文件等反序列化为给定Java类型的通用方法。
目标类型在这些方法的参数中给出。
EG。类型可以作为Class<T>
给出,就像方法
public <T> T readValue(String content, Class<T> valueType)
返回相同的T
对象(因此可以使用类型安全)。
但它也可以作为TypeReference<T>
(可以编码复杂的泛型类型)给出,因此可以构建例如。 new TypeReference<List<Long>> { }
告诉ObjectMapper
需要将输入反序列化为longs列表 - 例如,可以传递它。进入方法:
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(String content, TypeReference valueTypeRef)
但该方法需要原始 TypeReference
而非通用TypeReference<T>
,因此需要手动为调用添加通用参数:
objectMapper.<List<Long>>readValue(input, listOfLongs)
如果在提供的类型中出错,编译器就无法捕获它。如果方法签名是
,这不会有问题public <T> T readValue(String content, TypeReference<T> valueTypeRef)
这将告诉编译器返回的值始终与提供的TypeReference
的泛型参数的类型相同,类似于它与Class<T>
的工作方式。
我的问题是 - 这样的API背后的原因是什么?为什么Jackson方法采用原始TypeReference
?当返回的对象实际上是由TypeReference
的泛型参数引用的不同类型时,是否存在任何有效情况?
convertValue
方法不是原始类型,而是通配符:
public <T> T convertValue(Object fromValue, TypeReference<?> toValueTypeRef)
,同样readValues
:
public <T> MappingIterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef)
和readValue(JsonParser, TypeReference)
实际上takes a fully qualified generic parameter:
public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef)
答案 0 :(得分:3)
已经reported as an issue,但标记为3.x
。
图书馆的作者发表了一篇评论,解释了为什么还没有纠正这个问题:
看起来
ObjectMapper
API(也可能是ObjectReader
)省略了与TypeReference
匹配的类型变量。这对改变是有意义的,但很可能会导致一些源兼容性问题(不是二进制),所以可能在3.0而不是更早的时候这样做。
答案 1 :(得分:-1)
TypeReference
抽象类不能直接用作通用信息的容器。这来自javadoc:
此通用抽象类用于获取完整的泛型类型 分类信息;它必须转换为ResolvedType 实现(由来自&#34; databind&#34; bundle的JavaType实现) 使用
即使ObjectMapper
接受了参数化TypeReference
,它也无法完成工作,因为所有通用规范(如new TypeReference<List<Long>> { }
)都会在运行时完全删除。
要将通用信息传递给杰克逊的ObjectMapper
,您需要创建一个JavaType
个实例:
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, Long.class);
然后
List<Long> list = mapper.readValue(..., type);