(After OP commented that in fact the JSON looks like this, I completely updated the answer.)
Gson 2.0的解决方案+
I just learned that with newer Gson versions this is extremely simple:
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:
{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:事实证明,除非你使用的是Gson的2.0之前版本,否则你并不是一个真正的自定义反序列化程序.但知道如何执行custom deserialisation (and serialisation) in Gson次还是很有用的,而且这通常可能是最好的方法,这取决于你想如何使用解析的数据.)
所以我们确实在处理随机/可变字段名.(当然,这种JSON格式不是很好;这种数据应该在JSON array之内,在这种情况下,它可以很容易地读入列表.哦,我们仍然可以解析它.)
First, this is how I would model the JSON data in Java objects:
// 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 deserialiser for the top level object (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);
}
}
需要注意的一个关键点是对101的调用,它将重新运行所有顶级字段(名称如"1145"、"1148"等).This Stack Overflow answer帮助我解决了这个问题.
Complete parsing code below. Note that you need to use registerTypeAdapter()
to register the custom serialiser.
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 example that I used for testing. Besides Gson, it uses Guava library.)