使用GSon </object,>反序列化Map <object,object =“”>

时间:2011-03-22 19:14:42

标签: java object gson

我有一个包含类似混合的Map,就像这个简单的例子一样

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,没有Integer,没有String。输出看起来像

a : java.lang.Object@48d19bc8
b : java.lang.Object@394a8cd1
c : java.lang.Object@4d630ab9

我能以某种方式修复它吗?我希望默认情况下会正确处理这些简单的案例。

我知道无法始终保留有关该类型的信息,并且{J}可能1"1"表示完全相同。但是,返回普通的无内容对象对我来说毫无意义。

更新:序列化版本(即上面的string)看起来不错:

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

5 个答案:

答案 0 :(得分:7)

Gson并不那么聪明。而是在Javabean类的风格中提供清晰的静态数据结构,以便Gson了解应该将单独的属性反序列化为什么类型。

E.g。

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。这是一个快速的例子。

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

}

您使用如下:

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

答案 1 :(得分: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();

答案 2 :(得分:4)

升级到Gson 2.1。它打印出来:

a : 1.0
b : a
c : 2.0

答案 3 :(得分:-1)

您正在将数据存储在地图中。看起来您需要将对象转换为您需要的类型。

答案 4 :(得分:-1)

如果你想要Map<Object, Object>的JSON字符串,我认为json-simple是比Gson更好的选择。

这是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