如何使用Gson解码未知字段的JSON? [英] How to decode JSON with unknown field using Gson?

查看:203
本文介绍了如何使用Gson解码未知字段的JSON?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的JSON与此类似:

  {
unknown_field:{
field1 :str,
field2:str,
field3:str,
field4:str,
field5: str
},......
}

I创建的类来映射此JSON

  public class MyModel implements Serializable {
private int id;
私有HashMap< String,Model1>楷模;

//这里是id和模型的getters和setter
}



<



但是它不起作用。



p类和类Model1是一个简单的类,只有String字段。 > 编辑 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,
人口:nul l,
region_name:拉贾斯坦邦
},
...
}

$ (OP之后评论说,其实 JSON )



Gson 2.0 +的解决方案



刚刚了解到对于较新的Gson版本,这非常简单:

  GsonBuilder builder = new GsonBuilder(); 
Object o = builder.create()。fromJson(json,Object.class);

创建的对象是一个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 =旁遮普语,
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}
...



< h2>使用自定义反序列化器的解决方案

NB :原来你并不是真正的自定义反序列化器, 2.0版本的Gson,但仍然知道如何执行 gson中的自定义反序列化(和序列化),它可能通常是最好的方法,具体取决于n如何使用解析的数据。)



所以我们确实在处理随机/变化的字段名称。 (当然,这个JSON格式不是很好,这种数据应该放在一个JSON数组里面,在这种情况下,它可以很容易地读入一个List中。呵呵,我们仍然可以解析)



首先,我将如何在Java对象中建模JSON数据:

  //个别城市的信息
公共类城市{
String citiesId;
字符串城市;
字符串regionName;
//等等
}

//顶层对象,包含许多城市的信息
public class CityList {
List< City> ;城市;

public CityList(列出< City>城市){
this.cities = cities;
}
}

然后,解析。处理这种JSON的一种方法是为顶级对象(CityList)创建一个自定义反序列化器



类似这样:

  public class CityListDeserializer实现JsonDeserializer< CityList> ; {

@Override
public CityList反序列化(JsonElement元素,类型类型,JsonDeserializationContext上下文)throws JsonParseException {
JsonObject jsonObject = element.getAsJsonObject();
列表<城市> cities = new ArrayList< City>(); (Map.Entry< String,JsonElement>条目:jsonObject.entrySet()){
//对于单个City对象,我们可以使用默认的反序列化:
City city = context.deserialize (entry.getValue(),City.class);
cities.add(city);
}
返回新CityList(城市);
}

}

需要注意的一个关键点是调用 jsonObject.entrySet() ,它会回退所有顶级字段(名称如1145,1148等)。 这个堆栈溢出答案帮助我解决了这个问题。



完成解析代码如下。请注意,您需要使用 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);

(以下是完整的我用来测试的可执行示例除了Gson,它使用Guava库。)


I have JSON similar to this :

{
  "unknown_field": {
    "field1": "str",
    "field2": "str",
    "field3": "str",
    "field4": "str",
    "field5": "str"
  }, ......
}

I created classes to map this 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.

But it doesn't work.

Edit: the JSON format 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"
    }, 
    ...
}

解决方案

(After OP commented that in fact the JSON looks like this, I completely updated the answer.)

Solution for 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: 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.)

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.)

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);
    }

}

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 answer helped me solve this.

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.)

这篇关于如何使用Gson解码未知字段的JSON?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆