Java gson-多态变量的自定义反序列化程序

Java gson-多态变量的自定义反序列化程序,java,gson,Java,Gson,我使用gson将java对象与json对象进行转换。我遇到了多态性问题 我有这样的请求: { "method": "getUser", "methodParameters": { "a": "b", "c": "d", "e": "f", "data": { "u": "v", "x": "y" } }, "version": "1.3" } 每个请求方法都有不同类型的数据对象。自然地,每个数据对象都扩展了一个名为

我使用gson将java对象与json对象进行转换。我遇到了多态性问题

我有这样的请求:

{
  "method": "getUser",
  "methodParameters": {
    "a": "b",
    "c": "d",
    "e": "f",
    "data": {
      "u": "v",
      "x": "y"
    }
  },
  "version": "1.3"
}
每个请求方法都有不同类型的数据对象。自然地,每个数据对象都扩展了一个名为RequestData的基类

我试图创建一个自定义反序列化器,但由于保存该方法的是请求对象而不是数据对象,因此我无法找到一种方法来知道反序列化到哪个对象


在反序列化数据对象时是否可能以某种方式获得方法值,或者是否有其他更好的方法来解决此问题?谢谢。

当您反序列化此示例json字符串时,自定义反序列化程序将具有如下方法头:

public YOUR_CLASS deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
(通过GsonBuilder对象中的registerTypeAdapter()方法添加此反序列化器)

您可以将JsonElement转换为字符串,提取methodParameters,并基于每个RequestData子类的典型内容实例化特定类。
比如说,我们有MyRequestData,这个类有10个参数。我正在检查我的json字符串,如果它有这么多参数,则返回这个特定实例。当然,您可以首先反序列化methodParameters(在反序列化器类中)以映射类,然后分析它以选择正确的类

我遇到了一个类似的问题:正如Tomek所指出的,您需要一个自定义的反序列化程序,以及一个特定的JSON字段,您将在运行时使用该字段来决定执行哪个子类

将以下类视为基类:

// Base class for a server sent event
public class ServerEvent 
{
    public static final String TYPEFIELDNAME = "eventType";

    // Event type is used during deserialization to choose the right subclass
    private final String eventType;

    public ServerEvent(String eventType) 
    {
        this.eventType = eventType;
    }

    public String toString()
    {
        return "eventType: " + eventType;
    }
}
ServerEvent有两个子类,每个子类具有不同的属性:

public class EventA extends ServerEvent 
{   
    private static final String EVENTTYPE = "eventa";
    private int data;

    public EventA() 
    {
        super(EVENTTYPE);
    }

    // Helper function to register this class with ServerEventDeserializer
    public static void register(ServerEventDeserializer deserializer) 
    {
        deserializer.registerEvent(EVENTTYPE, EventA.class);
    }

    public String toString()
    {
        return super.toString() + ", data = " + data;
    }
}

public class EventB extends ServerEvent 
{   
    private static final String EVENTTYPE = "eventb";
    private String name;

    public EventB() 
    {
        super(EVENTTYPE);
    }

    // Helper function to register this class with ServerEventDeserializer
    public static void register(ServerEventDeserializer deserializer) 
    {
        deserializer.registerEvent(EVENTTYPE, EventB.class);
    }

    public String toString()
    {
        return super.toString() + ", name = " + name;
    }
}
两种可能的输入可能是:

{ "eventType" : "eventa", "data" : 15 }
{ "eventType" : "eventb", "name" : "test" }
这是多态反序列化程序:

// This class handles the polymorphic deserialization of ServerEvent class
public class ServerEventDeserializer implements JsonDeserializer<ServerEvent>
{
    // Gson engine
    private Gson gson;

    // Map of subclasses
    private Map<String, Class<? extends ServerEvent>> eventRegistry;

    public ServerEventDeserializer()
    {
        gson = new Gson();
        eventRegistry = new HashMap<String, Class<? extends ServerEvent>>();
    }

    // Registers a ServerEvent subclass
    public void registerEvent(String event, Class<? extends ServerEvent> eventInstanceClass)
    {
        eventRegistry.put(event, eventInstanceClass);
    }

    @Override
    public ServerEvent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
    {
        try
        {
            // Get the JSON object
            JsonObject commandObject = json.getAsJsonObject();

            // Read the field named "ServerEvent.TYPEFIELDNAME"
            JsonElement commandTypeElement = commandObject.get(ServerEvent.TYPEFIELDNAME);

            // Query the eventRegistry map to instance the right subclass
            Class<? extends ServerEvent> commandInstanceClass = eventRegistry.get(commandTypeElement.getAsString());
            ServerEvent command = gson.fromJson(json, commandInstanceClass);

            return command;
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }
}
//此类处理ServerEvent类的多态反序列化
公共类ServerEventDeserializer实现JsonDeserializer
{
//Gson发动机
私人Gson;
//子类映射

私有映射谢谢你的回答!我不能看参数的数量,因为两个方法可以有相同数量的参数。它们甚至应该可以有完全相同的参数。你能详细说明methodparams的反序列化吗?好的,稍后我会。但我有一个问题,这两个类之间有什么区别?只有实现某些方法的定义?在这种情况下,不可能识别它们。然后您可以简单地添加额外的参数,例如“name”和特定类的构造函数集合名称。这将是最简单的解决方案。反序列化将很容易。