2011-03-22 110 views
8

我有一個包含的類型的混合物象在這個簡單的例子反序列化地圖<對象,對象>與GSON

final Map<String, Object> map = new LinkedHashMap<String, Object>(); 
map.put("a", 1); 
map.put("b", "a"); 
map.put("c", 2); 
final Gson gson = new Gson(); 
final String string = gson.toJson(map); 
final Type type = new TypeToken<LinkedHashMap<String, Object>>(){}.getType(); 
final Map<Object, Object> map2 = gson.fromJson(string, type); 
for (final Entry<Object, Object> entry : map2.entrySet()) { 
    System.out.println(entry.getKey() + " : " + entry.getValue()); 
} 

我會得到什麼是純Object S,NO Integer S,NO String秒的地圖。輸出看起來像

a : [email protected] 
b : [email protected] 
c : [email protected] 

我可以修復它嗎?我期望這種簡單的情況下將被默認正確處理。

我知道關於該類型的信息不能總是保留,並且可能1"1"在JSON中的含義完全相同。但是,返回簡單的無內容對象對我來說毫無意義。

更新:序列化版本(即上述string)看起來很好:

{"a":1,"b":"a","c":2} 
+0

你可以看看最後的字符串字符串?我相信這有助於理解這個問題。 – 2011-03-22 20:17:22

+0

我剛剛也遇到了這個......這就是爲什麼我使用我的JSONer ...它可能會慢一點,但它比Gson更通用:http://nu-art-infrastructure.blogspot.co .il/2013/03/jsoner.html – TacB0sS 2013-09-15 08:32:14

+0

@ TacB0sS:我已經遵​​循了「清晰和靜態的數據結構」建議。但是,讓Gson處理這個應該是非常簡單的。你是否在意提出問題? – maaartinus 2013-09-15 14:52:14

回答

6

Gson不是那麼聰明。而是提供一個清晰和靜態的Javabean類風格的數據結構,以便Gson理解單獨的屬性應該被反序列化到什麼類型。

例如

public class Data { 
    private Integer a; 
    private String b; 
    private Integer c; 
    // ... 
} 

結合

Data data1 = new Data(1, "a", 2); 
String json = gson.toJson(data1); 
Data data2 = gson.fromJson(json, Data.class); 

更新:根據意見,密鑰集似乎是不固定的(雖然你似乎能夠將它之後手動轉換不知道預先結構)。你可以創建一個custom deserializer。這是一個快速的例子。

final Gson gson = new GsonBuilder().registerTypeAdapter(Object.class, new ObjectDeserializer()).create(); 
// ... 
+0

Javabean肯定是不可能的,因爲密鑰集不固定。作爲一種解決方法,我可以使用'Map '並手動轉換類型(類似的東西),我只是想知道爲什麼GSon表現得奇怪。 – maaartinus 2011-03-22 20:55:55

+0

手動轉換類型的能力表明您事先知道數據結構。所以keyset不固定的論點是一個非參數。至於Gson,你可以考慮一個自定義的反序列化器,它決定了這個值是否是一個數字(正則表達式,解析器,Long#valueOf()等),並返回Long或String。另請參閱http://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a- Derialrializer – BalusC 2011-03-22 21:03:37

+0

我用一個示例更新了答案,您可能會發現它很有用。 – BalusC 2011-03-22 21:10:55

-1

您存儲在地圖中的數據。看起來你需要將對象轉換爲你需要的類型。

+0

當然,如果類型是String或Integer,它不能輸出java.lang.Object @ ...'。我還使用'getClass()'對其進行了雙重檢查。 – maaartinus 2011-03-22 20:27:13

4
Gson gson = new GsonBuilder() 
    .registerTypeAdapter(Object.class, new JsonDeserializer<Object>() { 
     @Override 
     public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     JsonPrimitive value = json.getAsJsonPrimitive(); 
     if (value.isBoolean()) { 
      return value.getAsBoolean(); 
     } else if (value.isNumber()) { 
      return value.getAsNumber(); 
     } else { 
      return value.getAsString(); 
     } 
     } 
    }).create(); 
-1

如果你想從Map<Object, Object> JSON字符串,我覺得json-simpleGson更好的選擇:

public class ObjectDeserializer implements JsonDeserializer<Object> { 

    @Override 
    public Object deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { 
     String value = element.getAsString(); 
     try { 
      return Long.valueOf(value); 
     } catch (NumberFormatException e) { 
      return value; 
     } 
    } 

} 
您使用如下

這是從http://code.google.com/p/json-simple/wiki/EncodingExamples一個簡單的例子:

//import java.util.LinkedHashMap; 
//import java.util.Map; 
//import org.json.simple.JSONValue; 

Map obj=new LinkedHashMap(); 
obj.put("name","foo"); 
obj.put("num",new Integer(100)); 
obj.put("balance",new Double(1000.21)); 
obj.put("is_vip",new Boolean(true)); 
obj.put("nickname",null); 
String jsonText = JSONValue.toJSONString(obj); 
System.out.print(jsonText); 

結果:{"name":"foo","num":100,"balance":1000.21,"is_vip":true,"nickname":null}

對於解碼,參考http://code.google.com/p/json-simple/wiki/DecodingExamples

4

升級至Gson 2.1。它打印此:

a : 1.0 
b : a 
c : 2.0