【问题标题】:Retrofit Android : java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path改造Android:java.lang.IllegalStateException:预期BEGIN_ARRAY但在第1行第2列路径是BEGIN_OBJECT
【发布时间】:2015-09-27 13:43:02
【问题描述】:

之前有人问过类似的问题。但他们都没有为我工作。 我正在尝试返回一个订阅者正在收听的 observable。 每次使用 "java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $" 调用订阅者的 onError() 方法时都会出现此错误。

这是我的代码:

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.");
                }
            })

【问题讨论】:

  • List 但响应是包含 json 数组的 json 对象。我认为您需要使用 pojo 模式。使用 GSON 从 json 到对象数组列表映射。如果你没有明白我的意思,请告诉我。
  • 你知道json基础吗?不!学习它,例外就会很明显。
  • @BhavdipPathar 你的帮助会更好。
  • 请贴出RetroFitInterface的代码。
  • @CommonsWare 它已经存在了

标签: android json gson retrofit observable


【解决方案1】:

目前您尝试将 json 反序列化为 List&lt;String&gt; 类型。但是List&lt;&gt; 在 json 中表示如下:[object1, object2, object3]。另一方面,您的 json 实际上是一个对象,它包含列表。

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

相当于上述 json 的 POJO(java 类)如下所示:

public class LocationsResponse {

  List<String> locations;
  String success;

}

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

public interface RetroFitInterface {

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

【讨论】:

  • 我必须添加 @SerializedName("locations") 才能使其正常工作。
  • afaik gson 不需要 @SerializedName 如果 java 字段与 json 中的名称相同,但没关系
【解决方案2】:

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

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;
}

}

把这个类放在你有的合适的包里。在下一步中,我将更新您的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();
                    }
                }
            })

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

【讨论】:

  • 如果您不想使用 Jackson 注释,可以将其删除。
  • 你能理解吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-08
相关资源
最近更新 更多