[英]Deserialise a generic class , with unknown generic type - Jackson
public class MessageModel<T> {
T body;
}
现在T
可以是Cricket
或Football
类型的对象。 现在这个类被序列化并发布到队列中。 在消费时,反序列化并将消息类型识别为板球或足球的最佳方法是什么,以便调用相应的服务。 我正在使用杰克逊进行序列化。
我尝试在序列化过程中引入一个新的属性Type
,并且在反序列化过程中将首先读取为 json 对象,识别类型并再次使用杰克逊反序列化,因为类型是已知的。 前任:
JSONObject jsonObject = new JSONObject(message);
String messageType = jsonObject.optString("message_type");
objectMapper.readValue(message,new TypeReference<MessageModel<messageType>>(){});
但正在寻找更好的方法。
在消费时,反序列化并将消息类型识别为板球或足球的最佳方法是什么,以便调用相应的服务。
这是不可能的。 泛型不是这样工作的。
泛型仅在编译时涉及。 当您的程序运行时,来自泛型的类型信息不再存在。 Java 泛型教程中有大量信息和示例。
作为一个简单的例子,这里有两个简单的类:
class MessageModel<T> {
}
class Cricket {
}
如果我们创建一个新的MessageModel<Cricket>
,它会编译并运行良好。
MessageModel<Cricket> cricket = new MessageModel<>();
但在运行时, cricket
仅被识别为MessageModel
的一个实例——没有证据表明Cricket
类以任何方式关联。 作为一点证据,要求cricket
对象在运行时报告自己的类,它将自己打印为MessageModel
:
System.out.println("runtime: " + cricket.getClass());
runtime: class MessageModel
这种行为在单个 JVM 中,但如果您的程序序列化一个对象并将其发送到其他程序,则不会发生任何变化。 该其他程序也无法从序列化对象中确定原始Cricket
泛型类型。
如果您以后需要原始类,您可以执行以下操作,在对象构造时捕获原始类。 稍后,当接收程序需要知道Cricket
是原始类时,它可以调用getConcreteClass()
:
首先,修改MessageModel
:在对象构造时需要一个Class
,将该类保存为私有成员,添加getConcreteClass()
以公开它:
class MessageModel<T> {
private final Class concreteClass;
MessageModel(Class concreteClass) {
this.concreteClass = concreteClass;
}
public Class getConcreteClass() {
return concreteClass;
}
}
从那里,原始类在运行时可用:
MessageModel<Cricket> cricket = new MessageModel<>(Cricket.class);
System.out.println("getClass() : " + cricket.getClass());
System.out.println("getConcreteClass() : " + cricket.getConcreteClass());
getClass() : class MessageModel
getConcreteClass() : class Cricket
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.