使用 GSON 反序列化嵌套对象
Deserialize nested object with GSON
我正在尝试反序列化以下结构
{ meta: { keywords: [a, b, c, d]} ... }
其他有效结构是
{ meta: { keywords: "a,b,c,d"} ... }
和
{ meta: {keywords: "a"} ...}
我有这个类
public class Data {
@PropertyName("meta")
MetaData meta;
...
}
public class MetaData {
List<String> keywords;
...
}
和自定义解串器
public static class CustomDeserilizer implements JsonDeserializer<MetaData>{
@Override
public MetaData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<String> keywords = null;
Gson gson = new Gson();
MetaData metaData = gson.fromJson(json, AppMetaData.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("keywords")) {
JsonElement elem = jsonObject.get("keywords");
if (elem != null && !elem.isJsonNull()) {
if (jsonObject.get("keywords").isJsonArray()) {
keywords = gson.fromJson(jsonObject.get("keywords"), new TypeToken<List<String>>() {
}.getType());
} else {
String keywordString = gson.fromJson(jsonObject.get("keywords"), String.class);
keywords = new ArrayList<String>();
list.addAll(Arrays.asList(keywordString.split(",")));
}
}
}
metaData.setKeywords(keywords);
}
然后我尝试应用反序列化器:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Data.class,new CustomDeserilizer())
.create();
但是我遇到了一个解析错误,因为我正在尝试反序列化数据而不是元数据,我该如何应用这个反序列化器才能使其正常工作?
首先,将您的 class 重命名为元数据而不是元数据,并将关键字字符串而不是 List.Then 使用以下内容将您的 JSonString 映射到您的对象中。
Gson gson = new GsonBuilder().create();
Meta meta = gson.from(yourJsonString,Meta.class);
为了只获取关键词,你需要这个。
JsonObject jsonObject = new JsonObject(yourJSonString);
String data = jsonObject.getJsonObject("meta").getString("keywords");
keywords is a JsonObject not an JsonArray so you can't directly map it
onto List. You can split the string to get keywords in an array.
String keywords[] = data.split(",");
我解决了为我的 class 数据创建解串器的问题。
public static class DataDeserilizer implements JsonDeserializer {
@Override
public Data deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Gson gson = new Gson();
Data data = gson.fromJson(json, Data.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("meta")) {
JsonElement elem = jsonObject.get("meta");
if (elem != null && !elem.isJsonNull()) {
Gson gsonDeserializer = new GsonBuilder()
.registerTypeAdapter(MetaData.class, new CustomDeserilizer())
.create();
gsonDeserializer.fromJson(jsonObject.get("meta"), Data.class);
}
}
return data;
}
}
和
Gson gson = new GsonBuilder()
.registerTypeAdapter(Data.class,new DataDeserilizer())
.create();
很明显,但是有更优雅的解决方案吗?
这是一个简洁的解决方案,它利用 Java 继承来表示嵌套结构;因此不需要提供任何实际的实例成员字段(映射等)来捕获 GSON 映射的嵌套 String
数据。
第 1 步:为了可读性,创建一个空对象来表示嵌套映射
public class StateRegionCitiesMap extends HashMap<String, List<String>> {
}
第二步:添加一行实际代码来做映射; 没有其他 serialize/deserialize 逻辑需要管理
protected void loadContent(JsonObject stateRegionsJsonObject) {
HashMap<String, StateRegionCitiesMap> stateRegionCitiesMap =
mGson.fromJson(
stateRegionsJsonObject,
new TypeToken<HashMap<String, StateRegionCitiesMap>>() {
}.getType()
);
}
或者,您可以完全跳过包装器 class,直接将 <String, List<String>>
放入 GSON 调用中。但是,我发现一个明确的对象对 inform/remind 阅读代码的人有帮助,目的是什么。
示例JSON:
classStateRegionCitiesMap
表示多层映射结构,例如:
[US State] -> [State-Region Key] -> [Sub-Region Key] -> CitiesArray[]
"CA": {
"Central CA": {
"Central Valley": [
"FRESNO",
"VISALIA"
],
"Sacramento Area": [
"SACRAMENTO",
"EL DORADO HILLS"
]
},
我正在尝试反序列化以下结构
{ meta: { keywords: [a, b, c, d]} ... }
其他有效结构是
{ meta: { keywords: "a,b,c,d"} ... }
和
{ meta: {keywords: "a"} ...}
我有这个类
public class Data {
@PropertyName("meta")
MetaData meta;
...
}
public class MetaData {
List<String> keywords;
...
}
和自定义解串器
public static class CustomDeserilizer implements JsonDeserializer<MetaData>{
@Override
public MetaData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<String> keywords = null;
Gson gson = new Gson();
MetaData metaData = gson.fromJson(json, AppMetaData.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("keywords")) {
JsonElement elem = jsonObject.get("keywords");
if (elem != null && !elem.isJsonNull()) {
if (jsonObject.get("keywords").isJsonArray()) {
keywords = gson.fromJson(jsonObject.get("keywords"), new TypeToken<List<String>>() {
}.getType());
} else {
String keywordString = gson.fromJson(jsonObject.get("keywords"), String.class);
keywords = new ArrayList<String>();
list.addAll(Arrays.asList(keywordString.split(",")));
}
}
}
metaData.setKeywords(keywords);
}
然后我尝试应用反序列化器:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Data.class,new CustomDeserilizer())
.create();
但是我遇到了一个解析错误,因为我正在尝试反序列化数据而不是元数据,我该如何应用这个反序列化器才能使其正常工作?
首先,将您的 class 重命名为元数据而不是元数据,并将关键字字符串而不是 List.Then 使用以下内容将您的 JSonString 映射到您的对象中。
Gson gson = new GsonBuilder().create();
Meta meta = gson.from(yourJsonString,Meta.class);
为了只获取关键词,你需要这个。
JsonObject jsonObject = new JsonObject(yourJSonString);
String data = jsonObject.getJsonObject("meta").getString("keywords");
keywords is a JsonObject not an JsonArray so you can't directly map it onto List. You can split the string to get keywords in an array.
String keywords[] = data.split(",");
我解决了为我的 class 数据创建解串器的问题。
public static class DataDeserilizer implements JsonDeserializer {
@Override
public Data deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Gson gson = new Gson();
Data data = gson.fromJson(json, Data.class);
JsonObject jsonObject = json.getAsJsonObject();
if (jsonObject.has("meta")) {
JsonElement elem = jsonObject.get("meta");
if (elem != null && !elem.isJsonNull()) {
Gson gsonDeserializer = new GsonBuilder()
.registerTypeAdapter(MetaData.class, new CustomDeserilizer())
.create();
gsonDeserializer.fromJson(jsonObject.get("meta"), Data.class);
}
}
return data;
}
}
和
Gson gson = new GsonBuilder()
.registerTypeAdapter(Data.class,new DataDeserilizer())
.create();
很明显,但是有更优雅的解决方案吗?
这是一个简洁的解决方案,它利用 Java 继承来表示嵌套结构;因此不需要提供任何实际的实例成员字段(映射等)来捕获 GSON 映射的嵌套 String
数据。
第 1 步:为了可读性,创建一个空对象来表示嵌套映射
public class StateRegionCitiesMap extends HashMap<String, List<String>> {
}
第二步:添加一行实际代码来做映射; 没有其他 serialize/deserialize 逻辑需要管理
protected void loadContent(JsonObject stateRegionsJsonObject) {
HashMap<String, StateRegionCitiesMap> stateRegionCitiesMap =
mGson.fromJson(
stateRegionsJsonObject,
new TypeToken<HashMap<String, StateRegionCitiesMap>>() {
}.getType()
);
}
或者,您可以完全跳过包装器 class,直接将 <String, List<String>>
放入 GSON 调用中。但是,我发现一个明确的对象对 inform/remind 阅读代码的人有帮助,目的是什么。
示例JSON:
classStateRegionCitiesMap
表示多层映射结构,例如:
[US State] -> [State-Region Key] -> [Sub-Region Key] -> CitiesArray[]
"CA": {
"Central CA": {
"Central Valley": [
"FRESNO",
"VISALIA"
],
"Sacramento Area": [
"SACRAMENTO",
"EL DORADO HILLS"
]
},