Jackson TypeReference在扩展时是否有效?

以下片段是不言自明的。 您可以看到类型信息未被删除,但mapper不会获取类型信息。 我的猜测是jackson不允许这样,对吧? 如果我直接传递TypeReference,它会被正确反序列化。

public class AgentReq extends TypeReference<AgentResponse> {...} mapper.readValue(reader, new AgentReq<Map<String, Set>>()); 

如果我这样做它也不起作用:

 public class AgentReq { public TypeReference<AgentResponse> getTypeRef() { return new TypeReference<AgentResponse>() {}; } } mapper.readValue(reader, new AgentReq<Map<String, Set>>()).getTypeRef(); 

我正在使用2.1.5版。

编辑:为了将来参考,在解决问题时不要低估TypeReference构造函数。 在那里你可以直接看到它是否能够检索类型信息。 顺便说一句答案是否定的,你不能扩展TypeReference并期望它工作,你甚至不能覆盖它的getType()方法并为它提供从你的类中解析的类型信息,因为你可以得到的只是getClass()。 getGenericSuperClass()…你不能做getClass()。getGenericClass()

您需要了解TypeReference工作原理。 为此,我们进入源代码

 protected TypeReference() { Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class) { // sanity check, should never happen throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information"); } ... _type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; } 

Class#getGenericSuperclass() javadoc状态

返回表示此Class表示的实体(类,接口,基本类型或void)的直接超类的Type。

如果超类是参数化类型,则返回的Type对象必须准确反映源代码中使用的实际类型参数。

换句话说,如果我们可以执行new TypeReference() (我们不能,它是抽象的),它将返回类ObjectClass实例。 但是,使用匿名类(从类型扩展)

 new TypeReference(){} 

创建的实例的直接超类是参数化类型TypeReference ,根据javadoc,我们应该得到一个Type实例,它准确地反映源代码中使用的实际类型参数

 TypeReference 

然后,您可以使用getActualTypeArguments()[0])获取参数化类型,返回String

让我们举一个例子来使用匿名类和使用子类进行可视化

 public class Subclass extends TypeReference>{ public Subclass() { System.out.println(getClass().getGenericSuperclass()); System.out.println(((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]); } } 

运行

 new Subclass(); 

版画

 com.fasterxml.jackson.core.type.TypeReference> Test.AgentResponse 

符合javadoc规则。 Test.AgentResponse是源代码中的实际参数化类型。 现在,如果相反,我们有

 new Subclass(){}; // anonymous inner class 

我们得到了结果

 Test.Subclass class java.lang.String 

这也符合法案。 内部类现在直接从Subclass扩展, Subclass在源代码中使用参数String进行参数化。

您会注意到,使用Subclass匿名内部类,我们丢失了有关AgentResponsegenerics类型的信息。 这是不可避免的。


注意

 reader = new StringReader("{\"element\":{\"map-element\":[{\"name\":\"soto\", \"value\": 123}]}}"); obj = mapper.readValue(reader, new AgentReq>>()); 

将编译并运行,但类型AgentReq>>将丢失。 Jackson将使用默认类型来序列化JSON。 该element将被反序列化为AgentResponse ,而map-element将被反序列化为Map ,而JSON数组将被反序列化为ArrayList