首先,我看了一些其他的answers for similar questions,但它们不能满足我的特定情况。
我正在解析由主体和头部组成的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,但如果有必要的话,我不介意编写它们。
发布于 2017-02-18 17:27:15
我意识到,要求不涉及自定义Serializer/Deserializer的解决方案有点可笑,因为这正是使用它们的场景类型(我在想我可以使用自定义TypeAdapterFactory,但使用序列化程序/反序列化程序更容易)。
无论如何,对于我的场景,消息类的自定义序列化程序/反序列化程序的组合似乎工作得很好。由于我已经使用枚举来跟踪不同的消息用途及其字符串名称,因此我决定简单地向该枚举添加一个额外的字段来存储相应的正文类。
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相匹配,并且它似乎可以很好地反序列化不同类型的消息。
https://stackoverflow.com/questions/42309276
复制相似问题