Java 反序列化映射<;对象,对象>;与格森

Java 反序列化映射<;对象,对象>;与格森,java,object,gson,Java,Object,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 = n

我有一个包含混合类型的映射,就像这个简单示例中的那样

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());
}
我能修一下吗?我希望这些简单的案例在默认情况下会得到正确处理

我知道关于类型的信息不能总是被保留,而且可能
1
“1”
在JSON中的意思完全相同。然而,返回无内容的对象对我来说毫无意义

更新:序列化版本(即上面的
字符串
看起来很好:

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

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

格森没那么聪明。而是以Javabean类的风格提供一个清晰的静态数据结构,以便Gson了解单独属性应该反序列化到什么类型

例如

结合

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

更新:根据注释,键集似乎不是固定的(尽管您似乎可以在事后手动转换它,而不必事先知道其结构)。你可以创建一个。这里有一个简单的例子

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

}
Gson Gson=new GsonBuilder()
.registerTypeAdapter(Object.class,新的JsonDeserializer()){
@凌驾
公共对象反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
JsonPrimitive value=json.getAsJsonPrimitive();
if(value.isBoolean()){
返回值;
}else if(value.isNumber()){
返回值。getAsNumber();
}否则{
返回值.getAsString();
}
}
}).create();

如果您想要
Map
中的JSON字符串,我认为
JSON simple
Gson
更好

以下是一个简单的例子:

结果:
{“name”:“foo”,“num”:100,“balance”:1000.21,“is_vip”:true,“昵称”:null}

有关解码,请参阅。

升级至。它打印这个:

a : 1.0
b : a
c : 2.0

你能看看最后一个字符串是什么样子的吗?我相信这会有助于理解这个问题。我刚刚也遇到了这个问题。。。这就是为什么我使用我的JSONer。。。它可能会慢一点,但比Gson更通用:@TacB0sS:我遵循了“清晰静态数据结构”的建议。然而,让Gson处理这个问题应该很简单。你想提出一个问题吗?最糟糕的是,我在Android上使用GSON,在我的手机上它工作得很好,而在其他手机上它创造了你所描述的。。。我的解决方案也是清晰和静态的,但是在JSONer解析器中,您可以将映射和列表与嵌套的复杂对象一起使用,所有这些都在注释中解决!想提出一个关于什么的问题吗?他们知道这个问题,不是吗?当然不知道,如果类型是
String
Integer
,它就不能输出
java.lang。Object@...
。我还使用
getClass()
对其进行了双重检查。Javabean肯定是不可能的,因为密钥集不是固定的。作为一种解决方法,我可以使用
Map
手动转换类型(类似这样),我只是想知道为什么GSon的行为会如此奇怪。手动转换类型的能力表明您事先知道数据结构。因此,keyset未固定的参数是非参数。至于Gson,您可以考虑一个自定义的反序列化器,它确定值是一个数字(正则表达式、解析器、<代码>长α值()/代码>等),并返回<代码>长< /COD>或<代码>字符串< /代码>。另请参阅我用一个示例更新了答案,您可能会发现它很有用。“因此,keyset未固定的参数是一个非参数。”-这个“非参数”使Javabean解决方案无效。但是对于
ObjectDeserializer
示例,它工作得很好
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();
// ... 
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();
//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);
a : 1.0
b : a
c : 2.0