2011-03-22 70 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