我正在使用gson将java对象转换为json对象。我遇到了多态问题。
我有这些看起来像这样的请求:
{
"method": "getUser",
"methodParameters": {
"a": "b",
"c": "d",
"e": "f",
"data": {
"u": "v",
"x": "y"
}
},
"version": "1.3"
}
每种请求方法都有不同类型的数据对象。当然,每个数据对象都扩展了一个名为RequestData的基类。
我尝试创建一个自定义反序列化器,但因为它是请求对象而不是包含该方法的数据对象,所以我找不到一种方法来知道要反序列化的对象。
在反序列化数据对象时是否有可能以某种方式获取方法值,还是有其他更好的方法来解决这个问题?感谢。
答案 0 :(得分:2)
我遇到了类似的问题:正如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);
}
}
}
我写了一个可以下载的最小工作示例here。
答案 1 :(得分:0)
当您反序列化此示例时,json字符串自定义反序列化器将具有类似的方法标题:
public YOUR_CLASS deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
(通过GsonBuilder对象中的registerTypeAdapter()方法添加此反序列化器)
您可以将JsonElement转换为字符串,提取您的methodParameters,并根据每个RequestData子类的典型内容,您可以实例化特定的类。 可以说比如我们有MyRequestData,这个类有10个参数。我正在检查我的json字符串,如果它有这么多参数返回这个特定的实例。当然,您可以首先将methodParameters(在反序列化器类中)反序列化为Map类,然后对其进行分析以选择正确的类。