Java GSON序列化类型存储在不同对象中的多态对象

Java GSON序列化类型存储在不同对象中的多态对象,java,json,serialization,polymorphism,gson,Java,Json,Serialization,Polymorphism,Gson,首先,我看了其他一些,但它们不符合我的具体情况 我正在解析JSON消息,它由一个主体和一个头部组成,其中头部存储主体是什么类型的对象: { "body": { "eventName": "someEventName" }, "header": { "purpose": "event" } } 在Java中,我使用以下类对该结构进行了建模: public class Message { public Body body;

首先,我看了其他一些,但它们不符合我的具体情况

我正在解析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
)。但在这个场景中,情况并非如此――类型存储在另一个对象中,


解析这类对象的最佳方式是什么?为了简洁起见,我不想编写自定义的
序列化程序
/
反序列化程序
,但如果有必要,我也不介意编写它们。

我意识到要求一个不涉及自定义
序列化程序
/
反序列化程序
的解决方案有点荒谬,因为这正是他们将要使用的场景类型(我想我可以使用自定义的
TypeAdapterFactory
,但是使用序列化器/反序列化器更容易)

无论如何,在我的场景中,Message类的自定义序列化器/反序列化器的组合似乎可以正常工作。因为我已经使用了一个枚举来跟踪不同的消息用途及其字符串名称,所以我决定简单地向该枚举添加一个附加字段来存储相应的body类

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;
    }
}
消息序列化程序:

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;
    }
}
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);
    }
}
上述测试类打印:

{
  "body": {
    "eventType": "someEventName"
  },
  "header": {
    "purpose": "event"
  }
}

Event Type: someEventName

这个输出与我正在解析的消息的JSON相匹配,而且它似乎可以反序列化不同类型的消息。

我意识到,要求一个不涉及自定义
序列化程序的解决方案有点荒谬,因为这正是它们将要使用的场景类型(我想我可以使用自定义的
TypeAdapterFactory
,但是使用序列化器/反序列化器更容易)

无论如何,在我的场景中,Message类的自定义序列化器/反序列化器的组合似乎可以很好地工作。因为我已经使用枚举来跟踪不同的消息用途及其字符串名称,所以我决定只向该枚举添加一个附加字段来存储相应的body类

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;
    }
}
消息序列化程序:

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;
    }
}
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);
    }
}
上述测试类打印:

{
  "body": {
    "eventType": "someEventName"
  },
  "header": {
    "purpose": "event"
  }
}

Event Type: someEventName

此输出与我正在解析的消息的JSON匹配,并且它似乎可以反序列化不同类型的消息。

Body是一个父类…@Jawadlewwadi是的…我从来没有说过不是。在
Body
中的注释是提到Body的子类可以有其他字段,而不是Body是一个子类。Body是一个父类…@JawadLeWywadi是的…我从来没有说过不是。Body
中的注释是提到Body的子类可以有附加字段,而不是Body是子类。