Java Gson can';无法反序列化继承的类?
我有一个简单的Json结构,如:Java Gson can';无法反序列化继承的类?,java,json,gson,Java,Json,Gson,我有一个简单的Json结构,如: {"MessageType":"TimeData","TimeData":{"hh":12,"mm":13,"ms":15,"ss":14}} 我设计了以下类来反序列化它: public类JsonMessage { 公共枚举消息类型{ 你是谁, 时间数据 } JsonMessage(){ } 公共消息类型消息类型; } class-TimeData扩展了JsonMessage{ int hh; int-mm; int-ss; int-ms; 时间数据(){
{"MessageType":"TimeData","TimeData":{"hh":12,"mm":13,"ms":15,"ss":14}}
我设计了以下类来反序列化它:
public类JsonMessage
{
公共枚举消息类型{
你是谁,
时间数据
}
JsonMessage(){
}
公共消息类型消息类型;
}
class-TimeData扩展了JsonMessage{
int hh;
int-mm;
int-ss;
int-ms;
时间数据(){
}
}
我需要将反序列化分为两个阶段:
1-反序列化以读取消息类型
2-根据MessageType
代码很简单:
public void dispatch(Object message, IoSession session)
{
Gson gson = new Gson();
JsonMessage result = gson.fromJson(message.toString(), JsonMessage.class);
System.out.println(result.MessageType.toString());
switch (result.MessageType)
{
case WhoAreYou:{
//.....
break;
}
case TimeUpdate:
TimeData res = new Gson().fromJson(message.toString(), TimeData.class);
System.out.println(res.hh);
break;
default:break;
}
}
我的程序可以输入正确的开关大小写
(即TimeUpdate
),但无法正确解析它(println打印0而不是12)
你认为我哪里做错了什么?
谢谢你我通过以下方式实现了一个定制的
JsonDeserializer
解决了这个类似的问题
首先,根据类型和方法将子类附加到枚举,以根据枚举名称检索正确的类
:
enum MessageType {
WHO_ARE_YOU(WhoAreYou.class),
TIME_UPDATE(TimeUpdate.class);
public final Class<?> clazz;
MessageType(Class<?> clazz) { this.clazz = clazz; }
public static MessageType forName(String name) {
for (MessageType t : values())
if (name.equals(t.name()))
return t;
return NULL;
}
}
所有内容都由反射管理,以便创建正确的对象,然后相应地反序列化所有字段
我有一个复杂的对象层次结构,所以我更喜欢采用这种方式,让gson反序列化器管理一切。当然,您需要向gson解析器实例注册序列化程序
注意:根据Java标准,您对事物的命名是非常不正确的。枚举常量应为
全大写
,枚举类名应为单数(例如MessageType
)。实例变量应该是camelcased(例如,messageType
而不是messageType
)问题是,您的JSON表示一个包含您感兴趣的另一个对象的对象,而Java只是一个对象
实际上,您可以为每种类型编写反序列化程序,并在确定消息类型后使用它们:
public static void main(String[] args)
{
Gson gson = new GsonBuilder().registerTypeAdapter(TimeData.class, new TimeDataDeserializer()).create();
String json = "{\"MessageType\":\"TimeData\",\"TimeData\":{\"hh\":12,\"mm\":13,\"ms\":15,\"ss\":14}}";
JsonMessage message = gson.fromJson(json, JsonMessage.class);
switch(message.MessageType)
{
case TimeData:
TimeData td = new GsonBuilder()
.registerTypeAdapter(TimeData.class, new TimeDataDeserializer())
.create()
.fromJson(json, TimeData.class);
td.MessageType = message.MessageType
System.out.println(td.hh);
break;
default:
break;
}
}
class TimeDataDeserializer implements JsonDeserializer<TimeData>
{
@Override
public TimeData deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
JsonObject jo = je.getAsJsonObject().getAsJsonObject("TimeData");
Gson g = new Gson();
return g.fromJson(jo, TimeData.class);
}
}
publicstaticvoidmain(字符串[]args)
{
Gson Gson=new GsonBuilder().registerTypeAdapter(TimeData.class,new TimeDataDeserializer()).create();
字符串json=“{\'MessageType\':\'TimeData\',\'TimeData\':{\'hh\':12,\'mm\':13,\'ms\':15,\'ss\':14}”;
JsonMessage=gson.fromJson(json,JsonMessage.class);
开关(message.MessageType)
{
案例时间数据:
TimeData td=new GsonBuilder()
.registerTypeAdapter(TimeData.class,新的TimeDataDeserializer())
.create()
.fromJson(json,TimeData.class);
td.MessageType=message.MessageType
System.out.println(td.hh);
打破
违约:
打破
}
}
类TimeDataDeserializer实现JsonDeserializer
{
@凌驾
公共时间数据反序列化(JsonElement je,类型类型,JsonDeserializationContext jdc)
抛出JsonParseException
{
JsonObject jo=je.getAsJsonObject().getAsJsonObject(“时间数据”);
Gson g=新的Gson();
返回g.fromJson(jo,TimeData.class);
}
}
感谢您提供的解决方案。几天前我开始了Java编程,所以我需要阅读几遍代码才能理解。我现在就开始更改,并将立即让您知道结果。谢谢你,我很抱歉:在你的第一个代码片段中,我不得不将(MessageType t:values)的更改为(MessageType t:MessageType.values())
的,尽管如此,我还是遇到了一个错误:“非静态变量MessageType不能从静态上下文引用”我尝试了一下,但没有成功。你能帮个忙吗?将方法设置为静态的(是的,将值替换为值()
),你可以查看。我在这里回答了一个类似的问题。它仍然没有将整个响应转换为TimeData对象,因为MessageType是从父类而不是子类访问的。有没有解决这个问题的办法?
public static void main(String[] args)
{
Gson gson = new GsonBuilder().registerTypeAdapter(TimeData.class, new TimeDataDeserializer()).create();
String json = "{\"MessageType\":\"TimeData\",\"TimeData\":{\"hh\":12,\"mm\":13,\"ms\":15,\"ss\":14}}";
JsonMessage message = gson.fromJson(json, JsonMessage.class);
switch(message.MessageType)
{
case TimeData:
TimeData td = new GsonBuilder()
.registerTypeAdapter(TimeData.class, new TimeDataDeserializer())
.create()
.fromJson(json, TimeData.class);
td.MessageType = message.MessageType
System.out.println(td.hh);
break;
default:
break;
}
}
class TimeDataDeserializer implements JsonDeserializer<TimeData>
{
@Override
public TimeData deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException
{
JsonObject jo = je.getAsJsonObject().getAsJsonObject("TimeData");
Gson g = new Gson();
return g.fromJson(jo, TimeData.class);
}
}