小编典典

如何在Android的Retrofit中处理可能是ARRAY或OBJECT的参数?

json

我正在解析的API返回大小为1的数组的对象时遇到问题。

例如,有时API会响应:

{
    "monument": [
        {
            "key": 4152,
            "name": "MTS - Corporate Head Office",
            "categories": {},
            "address": {}
        },
        {
            "key": 4151,
            "name": "Canadian Transportation Agency",
            "categories": {},
            "address": {}
        },
        {
            "key": 4153,
            "name": "Bank of Montreal Building",
            "categories": {},
            "address": {}
        }
    ],
}

但是,如果monument数组只有1个项目,它将变成一个对象(请注意缺少[]括号),如下所示:

{
    "monument": {
        "key": 4152,
        "name": "MTS - Corporate Head Office",
        "categories": {},
        "address": {}
    }
}

如果我这样定义模型,则仅返回单个项目时会出现错误:

public class Locations {
    public List<Monument> monument;
}

如果仅返回单个项目,则会出现以下错误:

Expected BEGIN_OBJECT but was BEGIN_ARRAY ...

如果我这样定义我的模型:

public class Locations {
    public Monument monument;
}

API返回一个数组我得到了相反的错误

Expected BEGIN_ARRAY  but was BEGIN_OBJECT ...

我无法在模型中定义多个具有相同名称的项目。我该如何处理?

注意:我无法更改API。


阅读 219

收藏
2020-07-27

共1个答案

小编典典

作为我以前答案的补充,这是使用的解决方案TypeAdapter

public class LocationsTypeAdapter extends TypeAdapter<Locations> {

    private Gson gson = new Gson();

    @Override
    public void write(JsonWriter jsonWriter, Locations locations) throws IOException {
        gson.toJson(locations, Locations.class, jsonWriter);
    }

    @Override
    public Locations read(JsonReader jsonReader) throws IOException {
        Locations locations;

        jsonReader.beginObject();
        jsonReader.nextName();

        if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) {
            locations = new Locations((Monument[]) gson.fromJson(jsonReader, Monument[].class));
        } else if(jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
            locations = new Locations((Monument) gson.fromJson(jsonReader, Monument.class));
        } else {
            throw new JsonParseException("Unexpected token " + jsonReader.peek());
        }

        jsonReader.endObject();
        return locations;
    }
}
2020-07-27