Retrofit Call имеет одно и то же имя, другой тип данных - PullRequest
0 голосов
/ 03 июля 2019

вызов API

@GET("users/{user_id}/grid")
    Call<ArrayList<Grid>> getGrid(@Path("user_id") Integer id, @Header("Authorization") String authHeader);

Grid.class
public class Grid {

        @SerializedName("category")
        @Expose
        private String category;

        @SerializedName("type")
        @Expose
        private String type;

        @SerializedName("title")
        @Expose
        private String title;

        @SerializedName("equation_list")
        @Expose
        private List<Integer> equationList = null;  // This is the issue
}

Поле API response response_list содержит массив или строку Integer. пример:

"equation_list": "7", or 
"equation_list": [7],

Но я получил исключение

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Ожидаемый BEGIN_ARRAY, но был STRING в строке 1 строки 1586 пути $ [5] .equation_list

Как мне выполнить мое требование?

1 Ответ

1 голос
/ 03 июля 2019

Я думаю, вы можете создать тип для обработки обоих типов данных String и ArrayList . Затем вы можете реализовать пользовательский JsonAdapter для GSON для обработки пользовательской десериализации для этого типа.

Давайте создадим EquationList производное от java.util.ArrayList

/**
 * Custom type to handle both String and ArrayList<Integer> types
 *
 * @author Yavuz Tas
 *
 */
public class EquationList extends ArrayList<Integer> {

}

После того, как мы введем JsonAdapter для EquationList введите

/**
 * Custom JsonAdapter for GSON to handle {@link EquationList} converstion
 * 
 * @author Yavuz Tas
 *
 */
public class EquationListJsonAdapter extends TypeAdapter<EquationList> {

    @Override
    public void write(JsonWriter out, EquationList user) throws IOException {

        // Since we do not serialize EquationList by gson we can omit this part.
        // If you need you can check
        // com.google.gson.internal.bind.ObjectTypeAdapter class
        // read method for a basic object serialize implementation

    }

    @Override
    public EquationList read(JsonReader in) throws IOException {

        EquationList deserializedObject = new EquationList();

        // type of next token
        JsonToken peek = in.peek();

        // if the json field is string
        if (JsonToken.STRING.equals(peek)) {
            String stringValue = in.nextString();
            // convert string to integer and add to list as a value
            deserializedObject.add(Integer.valueOf(stringValue));
        }

        // if it is array then implement normal array deserialization
        if (JsonToken.BEGIN_ARRAY.equals(peek)) {
            in.beginArray();

            while (in.hasNext()) {
                String element = in.nextString();
                deserializedObject.add(Integer.valueOf(element));
            }

            in.endArray();
        }

        return deserializedObject;
    }
}

И, наконец, мы регистрируем наш адаптер в поле equationList в Grid

public class Grid {

    @SerializedName("category")
    @Expose
    private String category;

    @SerializedName("type")
    @Expose
    private String type;

    @SerializedName("title")
    @Expose
    private String title;

    @JsonAdapter(value = EquationListJsonAdapter.class)
    @SerializedName("equation_list")
    @Expose
    private EquationList equationList;

}

Это должно правильно обрабатывать ваши ответы, как показано ниже

"equation_list": "7", or "equation_list": [7]

Обратите внимание, что любой ответ String автоматически преобразуется в Integer и добавляется к EquationList в качестве элемента списка. Вы можете изменить это поведение, изменив реализацию в read методе EquationListJsonAdapter.

Надеюсь, это поможет. Ура!

...