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;
}
最初的问题是您声明层次结构的方式。 ListEntry
是 Map<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]
我正在尝试反序列化这种类型的 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;
}
最初的问题是您声明层次结构的方式。 ListEntry
是 Map<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]