反序列化泛型类,具有未知的泛型类型-Jackson

niwlg2el  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(132)
public class MessageModel<T> {
    T body;
}

现在T可以是CricketFootball类型的对象。现在这个类被序列化并发布到一个队列。在消费时,什么是最好的方法来反序列化并识别消息类型为Cricket或Football,以便调用相应的服务。我正在使用Jackson进行序列化。
我尝试在序列化过程中引入一个新属性Type,在反序列化过程中,首先读取为json对象,识别类型,然后再次使用Jackson反序列化,因为类型是已知的。例如:

JSONObject jsonObject = new JSONObject(message);
String messageType = jsonObject.optString("message_type");
objectMapper.readValue(message,new TypeReference<MessageModel<messageType>>(){});

而是在寻找更好的方法。

mcvgt66p

mcvgt66p1#

  • 在使用时,反序列化消息类型并将其标识为Cricket或Football以便调用相应服务的最佳方法是什么?*

这是不可能的。泛型不是这样工作的。
泛型只在编译时涉及。当你的程序运行时,泛型的类型信息不再存在。在Java Tutorial on generics中有很好的信息和例子。
下面是两个简单的类:

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

相关问题