反序列化 Map与 GSon

发布于 2024-10-25 13:30:31 字数 1039 浏览 2 评论 0原文

我有一个包含混合类型的 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 s。输出看起来像

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

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

我知道有关类型的信息并不总是能够保留,并且可能 1"1" 在 JSON 中的含义完全相同。然而,返回简单的无内容对象对我来说毫无意义。

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

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

I have a Map containing a mixture of types like in this simple example

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

What I get back are plain Objects, no Integers, no Strings. The output looks like

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

Can I fix it somehow? I'd expect that such simple cases will be handled correctly by default.

I know that the information about the type can't always be preserved, and possibly 1 and "1" means exactly the same in JSON. However, returning plain content-less objects just makes no sense to me.

Update: The serialized version (i.e. the string above) looks fine:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

¢好甜 2024-11-01 13:30:31

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

更新结合使用:根据评论,键集似乎不固定(尽管您似乎可以在事后手动转换它而无需事先了解结构)。您可以创建自定义反序列化器。这是一个简单的例子。

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 isn't that smart. Rather provide a clear and static data structure in flavor of a Javabean class so that Gson understands what type the separate properties are supposed to be deserialized to.

E.g.

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

in combination with

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

Update: as per the comments, the keyset seems to be not fixed (although you seem to be able to convert it manually afterwards without knowing the structure beforehand). You could create a custom deserializer. Here's a quick'n'dirty example.

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

}

which you use as follows:

final Gson gson = new GsonBuilder().registerTypeAdapter(Object.class, new ObjectDeserializer()).create();
// ... 
哑剧 2024-11-01 13:30:31
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();
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();
风苍溪 2024-11-01 13:30:31

升级到 Gson 2.1。它打印出这个:

a : 1.0
b : a
c : 2.0

Upgrade to Gson 2.1. It prints this:

a : 1.0
b : a
c : 2.0
南笙 2024-11-01 13:30:31

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

You are storing the data in a Map. It looks like you need to cast the object to the type you need.

浮生未歇 2024-11-01 13:30:31

如果您想要来自 Map 的 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

If you want a JSON string from Map<Object, Object>, I think json-simple is better choice than Gson.

This is a brief example from 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);

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

For decoding, refer to http://code.google.com/p/json-simple/wiki/DecodingExamples .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文