2013-04-25 104 views
2

我有一个简单的JSON结构等:Gson不能反序列化继承类吗?

{"MessageType":"TimeData","TimeData":{"hh":12,"mm":13,"ms":15,"ss":14}} 

和我设计的下列类来反序列化:

public class JsonMessage 
{ 
    public enum MessageTypes{ 
     WhoAreYou, 
     TimeData 
    } 
    JsonMessage(){ 
    } 
    public MessageTypes MessageType; 
} 
class TimeData extends JsonMessage{ 
    int hh; 
    int mm; 
    int ss; 
    int ms; 

    TimeData() { 
    }  
} 

我需要反序列化分成丝束阶段:

1-反序列化以读取MessageType

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

我的计划可以输入正确的switch-case(这是TimeUpdate),但它并不解析它正确(println打印0而不是12)

你认为我在哪里做错了什么? 谢谢

+1

你可以去看一下[http://stackoverflow.com/a/22081826/3315914]( http://stackoverflow.com/a/22081826/3315914)。我在那里回答了类似的问题。 – rpax 2014-02-28 08:05:09

回答

5

问题是,您的JSON表示一个Object,它包含您感兴趣的另一个对象,而Java只是一个对象。

实际上,你可以只写解串器为每种类型和使用他们,一旦你确定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); 
    } 
} 
1

我设法解决这个类似的问题,通过以下方式实现自定义JsonDeserializer

首先你连接到你的枚举基于类型和方法根据枚举名称检索正确Class<?>类的子类:

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

然后在deserialize方法我做了以下内容:

public JsonMessage deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException 
{ 
    JsonObject object = json.getAsJsonObject(); 
    String kind = object.get("messageType").getAsString(); 
    Class<?> clazz = MessageType.forName(kind).clazz; 
    JsonMessage result = null; 

    try { 
    result = (JsonMessage)clazz.newInstance(); 
    Field[] fs = clazz.getFields(); 

    for (Field f : fs) { 
     Object value = context.deserialize(object.get(f.getName()), f.getType());     
     if (value != null) 
     f.set(result, value); 
    } 
    } 
    catch (Exception e) { 
    e.printStackTrace(); 
    } 
} 

一切都由反射管理,以便创建正确的对象,然后相应地反序列化所有字段。

我有一个复杂的对象层次结构,所以我更愿意这样去让gson解串器管理一切。当然,您需要使用gson解析器实例注册序列化程序。

A注意事项:根据Java标准,您命名的东西是相当不正确的。枚举常量应为ALL_CAPITALIZED,枚举类名称应该是单数(例如,MessageType)。实例变量应该是基于camel的(例如,messageType而不是MessageType

+0

感谢您的解决方案。我几天前开始Java编程,所以我需要阅读代码几次才能理解。我现在就开始做出改变,很快就会让你知道结果。谢谢 – rahman 2013-04-25 16:56:45

+0

杰克,我很抱歉:在你的第一个代码片段中,我不得不将'for(MessageType t:values)'更改为'for(MessageType t:MessageType.values())',然后我得到错误:“非静态变量MessageType不能从静态上下文中引用“我尝试了一下,没有运气。你可以帮忙吗? – rahman 2013-04-25 17:15:14

+0

使方法'静态',你完成(是的,用'values()'替换'values') – Jack 2013-04-25 17:30:40