Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Gson can';无法反序列化继承的类?_Java_Json_Gson - Fatal编程技术网

Java Gson can';无法反序列化继承的类?

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; 时间数据(){

我有一个简单的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;
时间数据(){
}    
}
我需要将反序列化分为两个阶段:

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);
    }
}