改造 Android:java.lang.IllegalStateException:预期 BEGIN_ARRAY 但在第 1 行第 2 列路径中 BEGIN_OBJECT

Retrofit Android : java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path

之前问过类似的问题。但是 none 对我有用。 我正在尝试 return 一个订阅者正在收听的可观察对象。 每次调用订阅者的 onError() 方法时出现 "java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $" 这个错误。

这是我的代码:

public Observable<List<String>> getPlaces() {
    Retrofit retrofit = new Retrofit.Builder()
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
        .baseUrl(Urls.BASE_URL)
        .build();
    RetroFitInterface service = retrofit.create(RetroFitInterface.class);
    return service.getPlaces();
}




public interface RetroFitInterface {

    @Headers({
            "Accept: application/json",
            "Content-Type: application/json"
    })
    @GET(Urls.GET_POPULAR_LOCATIONS_URL)
    Observable<List<String>> getPlaces();
}

这是一个 JSON 回复:

{
    "locations": [
        "location1",
        "location2",
        "location3",
        "location4",
        "location5",
        "location6",
        "location7",
    ],
    "success": true
}

这就是我订阅订阅者的方式。

getPlaces().subscribeOn(Schedulers.io())
                .subscribe(new Observer<List<String>>() {
                    @Override
                    public void onCompleted() {
                        Log.d(TAG, "Search result onCompleted()!");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "Search result onError()! " + e.toString());
                    }

                @Override
                public void onNext(final List<String> result) {
                    Log.d(TAG, "This is never called.");
                }
            })

当前您尝试将 json 反序列化为 List<String> 类型。但是 List<> 在 json 中是这样表示的:[object1, object2, object3]。另一方面,您的 json 实际上是一个对象,其中 包含 列表。

{
    "locations": [
        "location1",
        "location2",
        "location3",
        "location4",
        "location5",
        "location6",
        "location7",
    ],
    "success": true
}

等价于上面 json 的 POJO (java class) 如下所示:

public class LocationsResponse {

  List<String> locations;
  String success;

}

所以要回答您的问题,您需要创建 LocationsResponse class 并使用 it 作为您的回复类型:

public interface RetroFitInterface {

    @Headers({
            "Accept: application/json",
            "Content-Type: application/json"
    })
    @GET(Urls.GET_POPULAR_LOCATIONS_URL)
    Observable<LocationsResponse> getPlaces();
}

您好首先,您需要将 json 响应转换为 POJO。为此,我使用这个 jsonschema2pojo 来生成 POJO class.

package com.example;

import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class LocationResponse {

@SerializedName("locations")
@Expose
private List<String> locations = new ArrayList<String>();
@SerializedName("success")
@Expose
private Boolean success;

/**
* 
* @return
* The locations
*/
public List<String> getLocations() {
return locations;
}

/**
* 
* @param locations
* The locations
*/
public void setLocations(List<String> locations) {
this.locations = locations;
}

/**
* 
* @return
* The success
*/
public Boolean getSuccess() {
return success;
}

/**
* 
* @param success
* The success
*/
public void setSuccess(Boolean success) {
this.success = success;
}

}

将此 class 放入您拥有的适当包中。在下一步中,我将更新您的 RetroFitInterface 界面,请参见下文:

public interface RetroFitInterface {

    @Headers({
            "Accept: application/json",
            "Content-Type: application/json"
    })
    @GET(Urls.GET_POPULAR_LOCATIONS_URL)
    Observable<LocationResponse> getPlaces();
}

最后,这是您订阅订阅者的方式。

getPlaces().subscribeOn(Schedulers.io())
                .subscribe(new Observer<LocationResponse>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                @Override
                public void onNext(final LocationResponse result) {
                    // your result is here
                    if(result.getSuccess()){
                            //result.getLocations();
                    }
                }
            })

如果您需要任何帮助,请告诉我。