JacksonTypeReference
允许通过子类化来具体化类型的泛型类型参数。例如:
final var typeRef = new TypeReference<List<MyType<MyArg>>>() {};
final List<MyType<MyArg>> list = mapper.readValue(input, typeRef);
final MyType<MyArg> first = list.get(0);
只有在子类化时知道完整类型时,这种方法才有效。在泛型方法中提取转换调用将不起作用:
<T> T convert(final String input) {
final var typeRef = new TypeReference<List<MyType<T>>>() {};
final List<MyType<T>> list = mapper.readValue(input, typeRef);
return list;
}
final MyType<MyArg> first = list.get(0);
(因为它会擦除为new TypeReference<List<MyType<Object>>>() {}
,而 很可能会被反序列化为List<MyType<Map<String, Object>>>
)。
我想反序列化和解包泛型类型的实例,而不在调用站点提供完整的类型签名。调用站点应该只关注内部(包装)类型,因为这是它将与之交互的唯一类型。给出以下记录定义:
private record MyResponse<T>(MyResult<T> result) {}
private record MyResult<T>(List<T> values) {}
private record MyStringValue(String name) {
@Override public String toString() {
return "'" + name + "'";
}
}
和一种方法
<T> MyResult<T> convert(final String input, final TypeReference<MyResponse<T>> typeRef) {
try {
return objectMapper.readValue(input, typeRef).result();
} catch (final JsonProcessingException ex) {
throw new RuntimeException(ex);
}
}
我怎样才能解开此函数的结果并仅返回一个实例T
,而不提供完整的类型引用TypeReference<MyResponse<MyResult<T>>>
?
我有:
<T> List<T> unwrap(final String input, final TypeReference<MyResponse<T>> typeRef) {
return convert(content, typeRef).values();
}
其必须被这样调用:
final List<MyStringValue> values = unwrap(input, new TypeReference<MyResponse<MyResult<MyStringValue>>>() {});
// or with diamond operator:
final List<AnotherType> values = unwrap(input, new TypeReference<>() {});
的调用者unwrap
不需要知道MyResponse
和MyResult
。是否可以unwrap
这样定义以隐藏这些实现细节?
final List<MyStringValue> values = unwrap(input, new TypeReference<MyStringValue>() {});
<T> List<T> unwrap(final String input, final TypeReference<T> typeRef) { // <- callers do not need to know about MyResponse/MyResult
final TypeReference<MyResponse<MyResult<T>>> wrappedTypeRef = typeRef.wrap(MyResponse<MyResult<T>>.class); // obviously not valid Java syntax
return convert(content, typeRef).values();
}
或者我是否仅仅因为类型擦除而被迫向此方法的所有调用者公开完整类型?
(在实际代码中MyResponse
和将是不同的具体类型:具有父类/子类并有 3 种实现)<T>
MyResponse
T
TypeReference
s 的设计目的仅仅是通过子类化来创建。您可以添加一个
convert
接受的新的重载JavaType
,并且可以使用动态创建它TypeFactory
。使用
constructParametricType
inunwrap
创建您想要的类型: