2013-04-25 85 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