【发布时间】:2016-04-08 16:27:24
【问题描述】:
我有一个通用的响应包装类:
public class Response <T> {
T response;
}
以及要包装的无关类:
public class ServiceResponse {
String someField;
}
当我提出服务请求时,我会收到类似于以下内容的 JSON 响应:
{ "code":200, "response":{"someField":"some text"} }
现在,我所有的服务响应都有相同的外包装,也就是说,它们都有:
{ "code":200, "timestamp":"....", "response":... }
但响应字段的实际格式/类型对于每个服务请求是不同的。当我反序列化响应时,我需要知道response 字段的类型,以便我可以创建适当的实例,如果反序列化是在Response 内完成的,我可以使用:
response = new T(jsonParser);
但是,我在一个由反射驱动的库中完成所有这些工作,因此我通常使用以下代码反序列化整个树:
wrapper = deserializer.parseObject(Response<ServiceResponse>.class)
但是,此时我的 parseObject 方法无法正确确定 T 的类型。
我可以使用类似的东西:
Response<ServiceResponse> response = new Response<>();
Field field = response.getClass().getDeclaredField("response");
Type type = field.getGenericType();
然后告诉我response 是T 类型,但我真正需要的是ServiceResponse
根据this SO question,我尝试转换为ParameterizedType,但这实际上似乎适用于Response<ServiceResponse> 类型的字段,而不是其中的实际字段(它失败了,因为type 不能转换为@ 987654337@)
有没有办法确定(在运行时)response 的原始类型?
最终,我可能不得不创建一个注释,提供有关如何反序列化字段的更多详细信息,可能是通过提供一个函数来执行此操作,但我更喜欢更透明的方法。
另一种可能性可能是在初始化时将 T 的 void 实例实际分配给响应,然后我可以从中获取实际类型...
【问题讨论】:
-
简短回答:不。长答案:提供有关您如何使用
Response的更多详细信息。您尝试获取Field的小sn-p 具有误导性,因为这样做没有意义,您已经知道您有ServiceResponse。你如何得到你的Response<?>? -
提供了有关用例的更多信息,但基本上我试图从网络服务请求中反序列化
Response<?>。在外层我知道什么?是,但在反序列化代码中我没有,所以我试图从可用的反射信息中恢复它。 -
是的,恐怕您的简短回答可能是实际答案,因为泛型确实是一种方便的编译器虚构。
-
那我有点糊涂了。如果在外层您知道
?是什么,那么只需将其提供给反序列化代码即可。如果在编译时你知道你想要一个Response<ServiceResponse>,那么只需将ServiceResponse.class传递给它,你就不需要(你不能,真的)从Response中检索它。在反序列化代码中,另一种方法是在反序列化策略的 JSON 中指示。 Jackson 有时会使用类似@class的字段,并将完全限定的目标类名称作为其值。 -
将
ServiceResponse传递给反序列化将需要针对这种特定情况进行专门化。我正在寻找一个通用的解决方案,它允许我使用:deserialize(Foo<X, Y, Z...>.class),它可以正确地实例化Foo对象中具有适当类型的任何字段。
标签: java reflection