改造:D/Response:预期 BEGIN_ARRAY 但在第 1 行第 2 列路径 $=BEGIN_OBJECT

Retrofit: D/Response: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

我想从 URL 的 JSON 响应中获取第一个 "City" 对象(或者将它们全部作为数组获取,然后在 RxJava 中使用 .map() 运算符获得第一个城市):

{
    totalResultsCount: 5,
    names: [
        {
            city: stockholm
        },
        {
            city: oslo
        },
        {
            city: london
        },
        {
            city: moscow
        },
        {
            city: mumbai
        }
    ]
}

这是负责获取此代码的代码:

public interface MyApi {

    @GET("searchJSON?")
    Observable<City[]> getPopulation(
        @QueryMap Map<String, String> queries
    );

}

和这个class

public class MyApiService{

    private final String baseUrl = "myapiurl";
    private MyApi api;
    private final Gson gson;
    private final OkHttpClient okHttpClient;

    public MyApiService(){
        gson = new Gson();
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
        okHttpClient = new OkHttpClient();
        okHttpClient.newBuilder().addInterceptor(httpLoggingInterceptor);
        buildApi();
    }

    private void buildApi(){
        api = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build()
                .create(MyApi.class);
    }

    public Observable<City> getPopulation(String city) {
        return api
                .getPopulation(city)
                .map(c -> c[0])
                .subscribeOn(Schedulers.io());
    }
}

当我从 activity 调用 getPopulation 时,我收到此消息:

D/Response: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

这是我的城市 class 的样子:

public class City {

    @SerializedName("city")
    private String name;

    public City(String name) {
        this.name = name;
    }
}

有什么想法吗?

编辑:

我尝试添加自定义反序列化器,例如:

public class MyDeserializer implements JsonDeserializer<City> {

    @Override
    public City deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonElement cities = json.getAsJsonObject().get("names");
        return new Gson().fromJson(cities, City.class);
    }

}

并更改为:

gson = new GsonBuilder()
                .registerTypeAdapter(City.class, new MyDeserializer())
                .create();

但我仍然得到与之前完全相同的响应。

您的自定义反序列化器使用 getAsJsonObject("names"),但名称是 json 响应中的 JsonArray。

names: [] // This is a JsonArray

names: {} // This is a JsonObject

我设法解决了这个问题。

我将 API 调用更改为:

@GET("searchJSON?")
    Observable<ResponseBody> getPopulation(
        @QueryMap Map<String, String> queries
    );

并且我将 api 调用方法更改为:

public Observable<City> getPopulation(String city) {
        return api
                .getPopulation(city)
                .map(c -> c.getCities().get(0))
                .subscribeOn(Schedulers.io());

并且我将我的 Serializeble POJO 更改为:

public class ResponseBody implements Serializable
{

    @SerializedName("totalResultsCount")
    @Expose
    private int totalResultsCount;
    @SerializedName("names")
    @Expose
    private List<City> cities = null;

    public ResponseBody() {
    }

    public ResponseBody(int totalResultsCount, List<City> cities) {
        super();
        this.totalResultsCount = totalResultsCount;
        this.cities = cities;
    }

    public int getTotalResultsCount() {
        return totalResultsCount;
    }

    public void setTotalResultsCount(int totalResultsCount) {
        this.totalResultsCount = totalResultsCount;
    }

    public List<City> getCities() {
        return cities;
    }

    public void setNames(List<City> cities) {
        this.cities = cities;
    }

}

public class City implements Serializable
{
    @SerializedName("name")
    @Expose
    private String name;

    public City() {
    }

    public City(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

我完全删除了自定义反序列化器。

这是我的 POJO 和错误选择 RxJava 操作的组合导致了我的问题。我希望这个答案能对以后的人有所帮助。

如果有人有更好的 solution/way 来处理这个问题,我将不胜感激。