改造: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 来处理这个问题,我将不胜感激。
我想从 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 来处理这个问题,我将不胜感激。