繁体   English   中英

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

[英]Deserialise a generic class , with unknown generic type - Jackson

public class MessageModel<T> {
    T body;
}

现在T可以是CricketFootball类型的对象。 现在这个类被序列化并发布到队列中。 在消费时,反序列化并将消息类型识别为板球或足球的最佳方法是什么,以便调用相应的服务。 我正在使用杰克逊进行序列化。

我尝试在序列化过程中引入一个新的属性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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM