Java 如何使用 Gson 解码具有未知字段的 JSON?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20442265/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to decode JSON with unknown field using Gson?
提问by NazarK
I have JSON similar to this :
我有与此类似的 JSON:
{
"unknown_field": {
"field1": "str",
"field2": "str",
"field3": "str",
"field4": "str",
"field5": "str"
}, ......
}
I created classes to map this json
我创建了类来映射这个 json
public class MyModel implements Serializable {
private int id;
private HashMap<String, Model1> models;
// getters and setter for id and models here
}
and class Model1 is a simple class only with String fields.
而类 Model1 是一个简单的类,只有字符串字段。
But it doesn't work.
但它不起作用。
Edit: the JSON formatlooks like this:
编辑:JSON 格式如下所示:
{
"1145": {
"cities_id": "1145",
"city": "Nawanshahr",
"city_path": "nawanshahr",
"region_id": "53",
"region_district_id": "381",
"country_id": "0",
"million": "0",
"population": null,
"region_name": "Punjab"
},
"1148": {
"cities_id": "1148",
"city": "Nimbahera",
"city_path": "nimbahera",
"region_id": "54",
"region_district_id": "528",
"country_id": "0",
"million": "0",
"population": null,
"region_name": "Rajasthan"
},
...
}
采纳答案by Jonik
(After OP commented that in fact the JSON looks like this, I completely updated the answer.)
(在 OP 评论说实际上JSON 看起来像这样之后,我完全更新了答案。)
Solution for Gson 2.0+
Gson 2.0+ 解决方案
I just learnedthat with newer Gson versions this is extremely simple:
我刚刚了解到,使用较新的 Gson 版本,这非常简单:
GsonBuilder builder = new GsonBuilder();
Object o = builder.create().fromJson(json, Object.class);
The created object is a Map (com.google.gson.internal.LinkedTreeMap), and if you print it, it looks like this:
创建的对象是一个 Map (com.google.gson.internal.LinkedTreeMap),如果你打印它,它看起来像这样:
{1145={cities_id=1145, city=Nawanshahr, city_path=nawanshahr, region_id=53, region_district_id=381, country_id=0, million=0, population=null, region_name=Punjab},
1148={cities_id=1148, city=Nimbahera, city_path=nimbahera, region_id=54, region_district_id=528, country_id=0, million=0, population=null, region_name=Rajasthan}
...
Solution using a custom deserialiser
使用自定义解串器的解决方案
(NB: Turns out you don't really a custom deserialiser unless you're stuck with pre-2.0 versions of Gson. But still it is useful to know how to do custom deserialisation (and serialisation) in Gson, and it may often be the best approach, depending on how you want to use the parsed data.)
(注意:事实证明,除非您坚持使用 Gson 2.0 之前的版本,否则您并不是真正的自定义反序列化器。但了解如何在 Gson 中进行自定义反序列化(和序列化)仍然很有用,而且通常可能是最好的方法,取决于你想如何使用解析的数据。)
So we're indeed dealing with random / varying field names. (Of course, this JSON format is not very good; this kind of data should be inside a JSON array, in which case it could be very easily read into a List. Oh well, we can still parse this.)
所以我们确实在处理随机/变化的字段名称。(当然,这种 JSON 格式不是很好;这种数据应该在一个JSON 数组中,这样它可以很容易地读入 List。哦,我们仍然可以解析它。)
First, this is how I would model the JSON data in Java objects:
首先,这是我在 Java 对象中建模 JSON 数据的方式:
// info for individual city
public class City {
String citiesId;
String city;
String regionName;
// and so on
}
// top-level object, containing info for lots of cities
public class CityList {
List<City> cities;
public CityList(List<City> cities) {
this.cities = cities;
}
}
Then, the parsing. One way to deal with this kind of JSON is to create a custom deserialiserfor the top level object (CityList).
然后,解析。处理此类 JSON 的一种方法是为顶级对象 (CityList)创建自定义反序列化器。
Something like this:
像这样的东西:
public class CityListDeserializer implements JsonDeserializer<CityList> {
@Override
public CityList deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = element.getAsJsonObject();
List<City> cities = new ArrayList<City>();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
// For individual City objects, we can use default deserialisation:
City city = context.deserialize(entry.getValue(), City.class);
cities.add(city);
}
return new CityList(cities);
}
}
A key point to notice is the call to jsonObject.entrySet()
which retuns all the top-level fields (with names like "1145", "1148", etc). This Stack Overflow answerhelped me solve this.
需要注意的一个关键点是jsonObject.entrySet()
返回所有顶级字段(名称如“1145”、“1148”等)的调用。这个 Stack Overflow 答案帮助我解决了这个问题。
Complete parsing code below. Note that you need to use registerTypeAdapter()
to register the custom serialiser.
完整的解析代码如下。请注意,您需要使用registerTypeAdapter()
来注册自定义序列化程序。
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(CityList.class, new CityListDeserializer());
Gson gson = builder.setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES).create();
CityList list = gson.fromJson(json, CityList.class);
(Here's a full, executable examplethat I used for testing. Besides Gson, it uses Guava library.)
(这是我用于测试的完整可执行示例。除了 Gson,它还使用 Guava 库。)