Gson - 使用嵌套映射反序列化 json

Gson - deserialize json with nested map

我正在尝试反序列化这种类型的 json

{
  "_embedded": {
    "list": [
      {
        "000000": {
          "date": "2015-07-10 14:29:15"
        }
      },
      {
        "111111": {
          "date": "2015-07-11 14:29:15"
        }
      }
    ]
  }
}

我设法在我的嵌入式对象中获取了一个列表,但列表条目是空的。

我的嵌入式 class 看起来像这样

public class Embedded {

    @SerializedName("list")
    private List<ListEntry> entries;
}

但我无法反序列化列表的条目。我认为问题在于地图嵌套在没有名称的对象中。

public class ListEntry {

    private Map<String, ListEntryInfo> map;
}

最初的问题是您声明层次结构的方式。 ListEntryMap<String, ListEntryInfo> 但没有 Map<String, ListEntryInfo>。要使其正常工作,您有以下三种选择:

  • ListEntry class 声明为 class ListEntry extends HashMap<String, ListEntryInfo> {},我认为这是个坏主意

  • 摆脱 ListEntry class 并像这样声明 entries 列表 @SerializedName("list") List<Map<String, ListEntryInfo>> entries;

  • 通过实现自定义反序列化器,使用我最初在下面描述的方法


如前所述,您可以编写一个自定义反序列化器,以便您拥有更多类型的条目列表。

由于一个 ListEntry 实例只有一个 ListEntryInfo 值映射到一个键,我会将结构更改为:

class ListEntry {
    private String key;
    private ListEntryInfo value;

    public ListEntry(String key, ListEntryInfo value) {
        this.key = key;
        this.value = value;
    }

    public String toString() {
        return key + " -> " + value;
    }
}

class ListEntryInfo {
    //assuming we store the date as a String for simplicity
    @SerializedName("date")
    private String date;

    public ListEntryInfo(String date) {
        this.date = date;
    }

    public String toString() {
        return date;
    }
}

现在你需要编写一个反序列化器来在你反序列化JSON:

时创建一个新的ListEntry实例
class ListEntryDeserializer implements JsonDeserializer<ListEntry> {
    @Override
    public ListEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        Iterator<Map.Entry<String, JsonElement>> ite = json.getAsJsonObject().entrySet().iterator();
        //you may want to throw a custom exception or return an "empty" instance there
        Map.Entry<String, JsonElement> entry = ite.next();
        return new ListEntry(entry.getKey(), context.deserialize(entry.getValue(), ListEntryInfo.class));
    }
}

此解串器将读取每个 ListEntry。由于它由单个键值对组成(在第一种情况下,字符串“000000”映射到一个 ListEntryInfo 等等),我们获取键并使用 [= 反序列化相应的 ListEntryInfo 28=]实例。

最后一步,是在解析器中注册它:

Gson gson = new GsonBuilder().registerTypeAdapter(ListEntry.class, new ListEntryDeserializer()).create();

运行 在你的例子中,你应该得到:

[000000 -> 2015-07-10 14:29:15, 111111 -> 2015-07-11 14:29:15]