如何将JSON数组序列化为Java HasMap,使用特定字段作为GSON的密钥?

时间:2016-05-16 14:50:50

标签: java json gson

例如,给定JSON:

[
{"id":"3", "location":"NewYork", "date":"yesterday"},
{"id":"4", "location":"Moscow", "date":"today"}
]

生成的HashMap:

<"3", POJOLocation("NewYork", "yesterday")>
<"4", POJOLocation("Moscow", "today")>

其中POJOLocation是Java对象:

class POJOLocation {
private String location;
private String date;
// etc
}

我尝试过使用自定义反序列化程序,但它真的很臃肿了泛型的令牌和hackish typeOf。也许有一个简单有效的解决方案?

2 个答案:

答案 0 :(得分:1)

也许创建一个POJOLocationId类:

class POJOLocationId {
private int id;
private String location;
private String date;
// etc
}

然后反序列化&amp;结束List生成HashMap的结果?

答案 1 :(得分:0)

Gson旨在将Java对象序列化为与JSON 等效的无痛。如果您尝试将Java数据结构表示为不同类型的JSON结构,那么编写序列化器和反序列化器将不会有很多乐趣。此时,您可以考虑使用较低级别的JSON解析器,并简单地实现您自己想要的解析。您可以考虑重构数据结构或数据,使其更加相似,而不是以JSON中的一种方式表示数据,而使用Java中的另一种方式(因而遇到转换它们的麻烦)。

那说Gson做的最简单的事情(实际上并没有那么糟糕,内存和时间)是使用包装器类型然后在使用它之前转换输入/输出。像这样的东西(借用Tom Mac的类型名称):

private static final Type LIST_TYPE =
    new TypeToken<List<POJOLocationId>>() {}.getType();

public String serialize(Map<Integer, POJOLocation> locations) {
  List<POJOLocationId> locationsList = original.entrySet().stream()
     .map(e -> new POJOLocationId(e.getKey(), e.getValue()).collect(toList());
  return gson.toJson(locationsList);
}

public Map<Integer, POJOLocation> deserialize(String json) {
  List<POJOLocationId> locationsList = gson.fromJson(json, LIST_TYPE);
  return locationsList.stream()
      .collect(toMap(l -> l.getId(), new POJOLocation(l)));
}

您当然可以使用自定义反序列化程序获得相同的行为,但这很有效,它很干净,而且很容易阅读。一旦这些方法返回,垃圾收集器就可以毫不费力地清理这些临时包装器。