改造-解析不带SerializedName的json

时间:2018-08-22 00:59:27

标签: android api gson retrofit

我有一个外部Web服务,它返回的名称为json,像这样;

[
  {
    "page": 1,
    "pages": 1,
    "per_page": "310",
    "total": 304
  },
  [
    {
      "id": "ABW",
      "iso2Code": "AW",
      "name": "Aruba",
      "region": {
        "id": "LCN",
        "iso2code": "ZJ",
        "value": "Latin America & Caribbean "
      },
      "adminregion": {
        "id": "",
        "iso2code": "",
        "value": ""
      },
      "incomeLevel": {
        "id": "HIC",
        "iso2code": "XD",
        "value": "High income"
      },
      "lendingType": {
        "id": "LNX",
        "iso2code": "XX",
        "value": "Not classified"
      },
      "capitalCity": "Oranjestad",
      "longitude": "-70.0167",
      "latitude": "12.5167"
    },
    {
      "id": "AFG",
      "iso2Code": "AF",
      "name": "Afghanistan",
      "region": {
        "id": "SAS",
        "iso2code": "8S",
        "value": "South Asia"
      },
      "adminregion": {
        "id": "SAS",
        "iso2code": "8S",
        "value": "South Asia"
      },
      "incomeLevel": {
        "id": "LIC",
        "iso2code": "XM",
        "value": "Low income"
      },
      "lendingType": {
        "id": "IDX",
        "iso2code": "XI",
        "value": "IDA"
      },
      "capitalCity": "Kabul",
      "longitude": "69.1761",
      "latitude": "34.5228"
    }
  ]
]

我有 CountriesResponse 类:

public class CountriesResponse {
    private ResponseDetails responseDetails;
    private List<Country> countries;

ResponseDetails

class ResponseDetails {
    @SerializedName("page")
    @Expose
    private int page;
    @SerializedName("pages")
    @Expose
    private int pages;
    @SerializedName("per_page")
    @Expose
    private String perPage;
    @SerializedName("total")
    @Expose
    private int total;

国家

public class Country {
    @SerializedName("name")
    private String name;

    @SerializedName("capitalCity")
    private String capital;

ApiInterface

public interface ApiInterface {
//http://api.worldbank.org/v2/countries/all?per_page=310&format=json
    @GET("countries/all")
    Call<ArrayList<Country>> getCountries(@Query("per_page") int per_page, @Query("format") String format);
}

CountriesResponse类中,我假设我要用@SerializedName注释属性。我如何解析json,看看json中的对象和数组没有名称。

1 个答案:

答案 0 :(得分:0)

1)您的呼叫返回了错误的类型。它应该返回您持有typedef struct { int type_identifier; // or uint8_t int access_mode; // or uint8_t union { char string[32]; struct { uint32_t val; uint32_t min; uint32_t max; uint32_t initial; } t_uint32; struct { double val; double min; double max; double initial; } t_double; struct { float val; float min; float max; float initial; } t_float; struct { char val; char min; char max; char initial; } t_char; } u; } valueType; 的顶级对象CountriesResponse,因为您想获取所有json,以便可以解析出匿名元素。

2)在ResponseDetails中,您有一个CountriesResponse,因为没有匹配的名称,因此无法在List<Country>.中使用序列化注释。必须手动将其反序列化。因此,在两个字段中都不要使用“ Country”。

3)使用Gson添加自定义解串器,请参见此处:Retrofit: how to parse a JSON array that combines an array and an object?

您需要将反序列化代码中的顶级JSON元素解析为包含2个元素的数组:

@SerializedName

要清楚地看到结构,可以使用https://jsoneditoronline.org并将JSON放在此处。 your JSON

您的反序列化器如下所示:

    final JsonArray jsonArray = json.getAsJsonArray();
    JsonObject rd = jsonArray get(0); //this is the ResponseDetails object
    CountriesResponse cr = new CountriesResponse();
    cr.setResponseDetails(rd);
    JsonArray countries = jsonArray.get(1) //<-- this is your List<Country>
    //now you must iterate list `countries`and create a new Country for each one then add it to the List<Country> in CountriesResponse

现在,您具有cr.getCountriesList()来显示数据。 JSONElements可能需要强制转换,但这实际上是要执行的操作。 Retrofit / POJO / JSON转换器不提供的一件事是匿名元素支持。

如果您需要将其保留在Room中,则还需要TypeConverter作为列表。