Дооснащение: D / Ответ: ожидалось BEGIN_ARRAY, но было BEGIN_OBJECT в строке 1, столбце 2, пути $ - PullRequest
0 голосов
/ 08 марта 2019

Я хочу получить первый объект "City" из этого ответа JSON с URL-адреса (или получить их все в виде массива, а затем использовать оператор .map () в RxJava для получения первого города):

{
    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
    );

}

и этого класса

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

Когда я вызываю getPopulation из действия, я получаю это сообщение:

D / Ответ: Ожидаемый BEGIN_ARRAY, но был BEGIN_OBJECT в строке 1 столбца 2 пути $

Вот как выглядит мой класс City:

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();

но я все равно получаю тот же ответ, что и раньше.

Ответы [ 2 ]

0 голосов
/ 08 марта 2019

Мне удается решить эту проблему.

Я изменил свои вызовы 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());

ИЯ изменил свои Сериализуемые 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, которые привели к моей проблеме.Я надеюсь, что этот ответ может помочь кому-то в будущем.

Если у кого-то есть лучшее решение / способ справиться с этим, я был бы признателен за комментарии.

0 голосов
/ 08 марта 2019

Ваш пользовательский десериализатор использует getAsJsonObject("names"), но имена - это JsonArray в вашем ответе json.

names: [] // This is a JsonArray

names: {} // This is a JsonObject
...