[英]GSON Serialize Polymorphic Object with Type Stored in a Different Object
首先,我针对类似的问题查看了其他一些答案 ,但是它们并不能回答我的特殊情况。
我正在解析由主体和标头组成的JSON消息,其中标头存储主体是什么类型的对象:
{
"body": {
"eventName": "someEventName"
},
"header": {
"purpose": "event"
}
}
在Java中,我使用以下类对这种结构进行了建模:
public class Message {
public Body body;
public Header header;
}
public class Header {
public String purpose; // Marks what child class the body of the message uses
}
public abstract class Body {
// Child classes store additional fields
}
// Example implementation of the body class
public class EventBody extends Body {
public String eventName; // Name of some event
}
经过研究,我发现RuntimeTypeAdapterFactory
通常用于解析/写入多态对象。 但是, RutimeTypeAdapterFactory
类依赖于存储在多态对象(即Body
)的基类中的类型。 但是在这种情况下,情况并非如此-类型存储在另一个对象Header
。
解析此类对象的最佳方法是什么? 我想避免为了紧凑而编写自定义的Serializer
/ Deserializer
,但是如果有必要,我不介意编写它们。
我意识到,寻求不涉及自定义Serializer
/ Deserializer
的解决方案有点荒谬,因为这正是它们所用的场景类型(我当时以为我可以摆脱自定义TypeAdapterFactory
,但是使用序列化器/反序列化器更容易)。
无论如何,对于我的情况,将Message类的自定义序列化器/反序列化器组合起来似乎可以正常工作。 由于我已经使用枚举来跟踪不同的消息用途及其字符串名称,因此我决定简单地向该枚举添加一个附加字段来存储相应的正文类。
MessagePurpose枚举:
public enum MessagePurpose {
EVENT("event", EventBody.class);
public final String purposeName;
public final Class bodyClass;
MessagePurpose(String purposeName, Class classi) {
this.purposeName = purposeName;
bodyClass = classi;
}
}
MessageSerializer:
public class MessageSerializer implements JsonSerializer<Message> {
@Override
public JsonElement serialize(Message message, Type type, JsonSerializationContext jsc) {
if(message == null) {
return null;
}
JsonObject messageObj = new JsonObject();
// Get the class representing the body object from the purpose enum
Class bodyClassType = message.getPurpose().bodyClass;
messageObj.add("body", jsc.serialize(message.getBody(), bodyClassType));
messageObj.add("header", jsc.serialize(message.getHeader(), Header.class));
return messageObj;
}
}
MessageDeserializer:
public class MessageDeserializer implements JsonDeserializer<Message> {
@Override
public Message deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException {
Header header = jdc.deserialize(je.getAsJsonObject().get("header"), Header.class);
// Get the class representing the body object from the purpose enum
Class bodyClassType = header.getPurpose().bodyClass;
Body body = jdc.deserialize(je.getAsJsonObject().get("body"), bodyClassType);
return new Message(body, header);
}
}
主要测试功能:
public static void main(String[] args) {
GsonBuilder gb = new GsonBuilder();
// Register the Message class since I need to access info in the header
gb.registerTypeAdapter(Message.class, new MessageDeserializer());
gb.registerTypeAdapter(Message.class, new MessageSerializer());
Gson gson = gb.setPrettyPrinting().create();
EventBody event = new EventBody(EventType.SOME_EVENT_NAME);
String eventJson = gson.toJson(event.getAsMessage());
System.out.println(eventJson);
Message newEvent = gson.fromJson(eventJson);
System.out.println("\nEvent type: " + ((EventBody) newEvent.getBody()).getEventName());
}
上面的测试类打印:
{
"body": {
"eventType": "someEventName"
},
"header": {
"purpose": "event"
}
}
Event Type: someEventName
此输出与我正在解析的消息的JSON匹配,并且似乎可以对不同类型的消息进行反序列化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.