2013-06-05 29 views
2

我目前正在開發瘦客戶端應用程序,通過JSON序列化的消息對象進行通信。服務器序列化消息,通過套接字發送,客戶端接收和反序列化。答案以同樣的方式發生。如何使用Gson在Java中反序列化和返回JSON中的對象而不必事先知道.class?

首先,讓我們假設消息類服務器和客戶端的定義兩者。

問題是Gson::fromJson函數需要一個.class/type對象來反序列化通過自省(可以理解),但是在我的應用程序中,可以在不知道.class的情況下接收多種類型的對象。

我的想法是創建這樣一個消息包裝:

class MessageWrapper { 
    public class MessageWrapper(Object message, MessageType type) { 
     this.message = message; 
     this.type = type; 
    } 

    // getters... 

    public enum MesssageType { 
     PLACEMENT, 
     UPDATE, 
     // ... 
    } 

    private final Object message; 
    private final MessageType type; 
} 

甚至通過確定type PARAM自省走得更遠。這個解決方案非常適合序列化(我重複一遍,這不是問題),但是在反序列化的時候,我會得到消息類型並且自己放棄消息,至少如果我不解析它兩次。通過Java「模板化」機制專門化MessageWrapper將我們帶回原始問題(我將有多個類可供選擇)。

另一個想法,就是送令牌識別消息,JSON字符串之前,如:

Placement={"foo": 2, "bar": "baz"} 

然後讀取令牌來確定的.class類型。這可以工作,但仍然有一個問題:我將如何返回從我的receive函數的值?我當然可以這樣做:

public Object receive(Reader stream) {} 

,並強制用戶做一個垂頭喪氣,但我寧願避免它。

編輯:這是因爲客戶端有一個反應器樣結構:它在一個循環中運行,並且將信息分配到適當的處理程序。

+0

你可以改變從服務器發送的結構?我的意思是通過使用另一個庫並在流中添加類型信息。 – eugen

+0

我在生成的JSON中有類型信息,可以是字段(第一種情況)或類型令牌(後一種情況)。 –

回答

3

使用GSON,如果有可能的消息的合理數量的,你可以創建一個包含所有這些類相似的(東西@Enrichman寫了,但你不需要檢查空值......)。例如,如果你有類

public class Response { 
    private Placement placement; 
    private Update update; 
    //more message types 
    //getters & setters 
} 

然後你就可以反序列化與迴應:

Gson gson = new Gson(); 
Response response = gson.fromJson(jsonString, Response.class); 

而且,它還將反序列化這個JSON:

{"placement": {...} } 

這:

{"update": {...} } 

和這個:

{"placement": {...}, "update": {...} } 

GSON將忽略不對應於任何屬性,在類,所以你可以使用一個單獨的類反序列化多個響應JSON響應的所有字段...

+0

很好的答案。我接受這一點,因爲它概述了「空字段沒有序列化」的關鍵點,並提出了另一個,因爲它提供了關鍵的直覺。遺憾的是,我無法以更簡單的方式達到相同的結果,也許一些CGlib魔法可以做到這一點。 –

+0

順便說一句,你可以選擇序列化或不空字段(至少你可以做這與傑克遜:http://stackoverflow.com/questions/11757487/how-to-tell-jackson-to-ignore-a-field-only -if-value-is-null)。 :) – Enrichman

3

編輯:

好吧,現在它更清晰。

關於有一系列定義對象的包裝是什麼?你有幾個處理程序?

我的意思是這樣的:

class HandlerWrapper { 
    private final Placement placement; 
    private final Update update; 
} 

然後客戶端將反序列化這一點,並檢查是否有非空屬性:

{"placement":{"foo": 2, "bar": "baz"}, "update":null, ...}

我knwo這是不是很漂亮,但我想不出關於其他東西..:/


OLD

我不認爲這其實是一個問題,因爲你可以在你的說明書說,你有從該特定情況下會發生什麼樣的對象。

例如,如果你調用一個API來獲取用戶,你會期望在一個對象User.class。獲得書籍(或whatelse)的API也是一樣。

(我希望我的理解問題)

+0

不,請參閱編輯。 –

相關問題