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

时间:2015-07-19 07:16:36

标签: json gson

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

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

我设法在嵌入对象中获取列表,但列表条目为空。

My Embedded类看起来像这样

public class Embedded {

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

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

public class ListEntry {

    private Map<String, ListEntryInfo> map;
}

1 个答案:

答案 0 :(得分:2)

最初的问题是您声明层次结构的方式。 ListEntryMap<String, ListEntryInfo>,但没有Map<String, ListEntryInfo>。为了使它工作,你有三个选择:

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

  • 摆脱ListEntry课程并声明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 1}}实例。

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

JsonDeserializationContext

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

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