为什么 Jackson 的 ObjectMapper 方法采用原始 TypeReference
Why Jackson’s ObjectMapper methods take raw TypeReference
Jackson 2 ObjectMapper
class 定义了许多通用方法,用于将 JSON 字符串、字节数组、文件等反序列化为给定的 Java 类型。
目标类型在这些方法的参数中给出。
例如。类型可以作为 Class<T>
给出,就像在方法
中一样
public <T> T readValue(String content, Class<T> valueType)
哪个 returns 相同的 T
对象(因此使用类型安全)。
但它也可以作为 TypeReference<T>
给出(它可以编码复杂的通用类型),因此可以构建例如。 new TypeReference<List<Long>> { }
告诉 ObjectMapper
输入需要被反序列化为一个 long 列表——它可以被传递,例如。进入方法:
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(String content, TypeReference valueTypeRef)
但该方法采用 raw 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
的泛型参数引用的不同类型时,是否存在任何有效的情况?
PS:同样令我困惑的是,相应的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)
TypeReference
摘要 class 并不意味着直接用作通用信息的容器。这是来自 javadoc:
This generic abstract class is used for obtaining full generics type
information by sub-classing; it must be converted to ResolvedType
implementation (implemented by JavaType from "databind" bundle) to be
used.
即使 ObjectMapper
接受了一个参数化的 TypeReference
,它也不会完成这项工作,因为像 new TypeReference<List<Long>> { }
这样的所有通用规范在 运行 时被完全删除。
要将通用信息传递给 Jackson 的 ObjectMapper
,您需要创建一个 JavaType
实例:
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, Long.class);
然后
List<Long> list = mapper.readValue(..., type);
它已经是 reported as an issue,但被标记为 3.x
。
库的作者有一条评论解释了为什么这个问题还没有得到更正:
Looks like ObjectMapper
API (and perhaps ObjectReader
too) omits type-variable matching with TypeReference
. This would make sense to change, but is likely to cause some source-compatibility issues (not binary), so perhaps do this in 3.0 and not earlier.
Jackson 2 ObjectMapper
class 定义了许多通用方法,用于将 JSON 字符串、字节数组、文件等反序列化为给定的 Java 类型。
目标类型在这些方法的参数中给出。
例如。类型可以作为 Class<T>
给出,就像在方法
public <T> T readValue(String content, Class<T> valueType)
哪个 returns 相同的 T
对象(因此使用类型安全)。
但它也可以作为 TypeReference<T>
给出(它可以编码复杂的通用类型),因此可以构建例如。 new TypeReference<List<Long>> { }
告诉 ObjectMapper
输入需要被反序列化为一个 long 列表——它可以被传递,例如。进入方法:
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T readValue(String content, TypeReference valueTypeRef)
但该方法采用 raw 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
的泛型参数引用的不同类型时,是否存在任何有效的情况?
PS:同样令我困惑的是,相应的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)
TypeReference
摘要 class 并不意味着直接用作通用信息的容器。这是来自 javadoc:
This generic abstract class is used for obtaining full generics type information by sub-classing; it must be converted to ResolvedType implementation (implemented by JavaType from "databind" bundle) to be used.
即使 ObjectMapper
接受了一个参数化的 TypeReference
,它也不会完成这项工作,因为像 new TypeReference<List<Long>> { }
这样的所有通用规范在 运行 时被完全删除。
要将通用信息传递给 Jackson 的 ObjectMapper
,您需要创建一个 JavaType
实例:
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, Long.class);
然后
List<Long> list = mapper.readValue(..., type);
它已经是 reported as an issue,但被标记为 3.x
。
库的作者有一条评论解释了为什么这个问题还没有得到更正:
Looks like
ObjectMapper
API (and perhapsObjectReader
too) omits type-variable matching withTypeReference
. This would make sense to change, but is likely to cause some source-compatibility issues (not binary), so perhaps do this in 3.0 and not earlier.