改造:如何解析结合了数组和对象的JSON数组? [英] Retrofit: how to parse a JSON array that combines an array and an object?

查看:97
本文介绍了改造:如何解析结合了数组和对象的JSON数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个使用Retrofit + OkHttp连接到REST API并使用JSON数据的Android应用.我对Retrofit相当陌生,因此我仍在学习它的工作原理,但到目前为止,一切都很顺利.但是,我遇到了一个异常问题.

I am working on an Android app that uses Retrofit+OkHttp to connect to a REST API and consume JSON data. I'm fairly new to Retrofit, so I'm still learning how it works, but so far it's been pretty smooth. However, I ran into an unusual problem.

其中一个端点返回的数据看起来像这样:

One of the endpoints returns data that looks a bit like this:

{
    "success": true,
    "data": [
        [
            {
                "field": "value1",
                ...
            },
            {
                "field": "value2",
                ...
            },
            ...
        ],
        {
           "info": "value",
           "info2": "value",
           "info3": "value",
        }
    ],
    "message": "This is the message."
}

在大多数情况下,这是一个非常标准的JSON响应.我们有一个状态"值,一个消息"值和一个数据"值,其中包含要返回的重要数据.但是,数据"的结构存在问题.如您所见,它是一个数组,但不仅是对象的数组.它的第一个元素是值的数组,第二个元素是 object .

For the most part, this is a pretty standard JSON response. We have a "status" value, a "message", and a "data" value containing the important data being returned. However, there's a problem with the structure of "data". As you can see, it's an array, but it's not just an array of objects. Its first element is the array of values, and its second element is an object.

Gson不喜欢这样.如果我想创建一个POJO来将其解析为使用Gson的方法,那么我希望这样做:

Gson doesn't like this. If I want to create a POJO to parse this into using Gson, I would expect to do something like this:

public class JsonResponse {

    @SerializedName("success")
    @Expose
    boolean success;

    @SerializedName("message")
    @Expose
    String message;

    @SerializedName("data")
    @Expose
    private ArrayList<MyObject> data = new ArrayList<>();

    public ArrayList<MyObject> getData() {
        return data;
    }

    public void setData(ArrayList<MyObject> data) {
        this.data = data;
    }
}

其中"MyObject"是这样的可包裹包裹:

Where "MyObject" is a Parcelable like this:

public class MyObject implements Parcelable {
      @SerializedName("field")
      @Expose
      boolean field;

      ...
}

但是那是行不通的,因为数据"不仅仅是对象的数组;这是一个包含对象数组和另一个顶级对象的数组.

But that doesn't work, because "data" isn't just an array of objects; it's an array containing the array of objects and another top-level object.

我可以将数据"定义为数组",并且它似乎可以解析值.但是随后它们作为通用的LinkedTreeMap对象出现,因此我失去了Gson的JSON-> POJO解析的优势.

I can define "data" as "Array", and it does seem to parse the values. But then they come out as generic LinkedTreeMap objects, so I lose the advantages of Gson's JSON->POJO parsing.

在Retrofit/Gson中,是否有一种优雅的方式来处理像这样的混合数组?我不对来自API的数据负责,因此我不认为更改此选项是一种选择.

Is there an elegant way to handle a mixed array like this in Retrofit/Gson? I'm not responsible for the data coming from the API, so I don't think changing that will be an option.

推荐答案

有一种方法.

添加自定义JsonDeserializer并手动处理该字段.

Add a custom JsonDeserializer and handle that field manually.

示例

public static class Deserializer implements JsonDeserializer<JsonResponse> {

    private final Gson gson = new GsonBuilder().create();

    @Override
    public JsonResponse deserialize(JsonElement json, Type typeOfT,
                                      JsonDeserializationContext context)
            throws JsonParseException {
        JsonResponse response = gson.fromJson(json, typeOfT);

        JsonObject jObject = json.getAsJsonObject();
        //Handle jObject here, and parse each object of data array 
        //accordingly to its type - JsonObject/JsonArray
        return response;
    }
}

您需要在全局Gson实例中注册它,如下所示:

You need to register it in your global Gson instance, like this:

new GsonBuilder()
            .registerTypeAdapter(JsonResponse.class, new JsonResponse.Deserializer())
            .create();

这篇关于改造:如何解析结合了数组和对象的JSON数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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