Это идеальный сценарий / схема. Однако я не могу контролировать ответы API, и это изменение не будет обратно совместимо для остальных клиентов. Спасибо
у библиотеку для использования Json API и сталкиваюсь с проблемой проектирования при использовании Gson в качестве библиотеки синтаксического анализа.
Одна из конечных точек возвращаетarray
из объектов, если все идет хорошо, вот так:
[
{
"name": "John",
"age" : 21
},
{
"name": "Sarah",
"age" : 32
},
]
Однако схема ошибок для всех конечных точек в API является jsonobject
вместо массива.
{
"errors": [
{
"code": 1001,
"message": "Something blew up"
}
]
}
Проблема возникает при моделировании этого в POJO. Поскольку схема ошибок является общей для всех конечных точек API, я решил сделать резюмеApiResponse
класс, который будет отображать только атрибут ошибок
public abstract class ApiResponse{
@SerializedName("errors")
List<ApiResponseError> errors;
}
public class ApiResponseError {
@SerializedName("code")
public Integer code;
@SerializedName("message")
public String message;
}
Теперь я хотел бы унаследовать отApiResponse
иметь отображение ошибок «бесплатно» и POJO для ответа конечной точки API. Однако объектом json верхнего уровня для этого ответа является массив (если серверу удается выполнить запрос), поэтому я не могу создать новый класс для сопоставления его так, как мне бы этого хотелось.
Я решил все еще создать класс, расширяющийApiResponse
:
public class ApiResponsePerson extends ApiResponse {
List<Person> persons;
}
И реализовал пользовательский десериализатор для правильного анализа json в зависимости от типа объекта верхнего уровня и установки его в правильное поле в следующем классе:
public class DeserializerApiResponsePerson implements JsonDeserializer<ApiResponsePerson> {
@Override
public ApiResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ApiResponsePerson response = new ApiResponsePerson();
if (json.isJsonArray()) {
Type personType = new TypeToken<List<Person>>() {}.getType();
response.persons = context.deserialize(json, personType);
return response;
}
if (json.isJsonObject()) {
JsonElement errorJson = json.getAsJsonObject().get("errors");
Type errorsType = new TypeToken<List<ApiResponseError>>() {}.getType();
response.errors = context.deserialize(errorJson, errorsType);
return response;
}
throw new JsonParseException("Unexpected Json for 'ApiResponse'");
}
}
Который я потом добавлю в Gson
Gson gson = new GsonBuilder()
.registerTypeAdapter(ApiResponsePerson.class, new DeserializerApiResponsePerson())
.create();
Есть ли способ смоделировать эти POJO и заставить Gson распознать эту структуру без необходимости вручную обрабатывать этот сценарий? Есть ли лучший способ сделать это? Я пропускаю какой-либо сценарий, в котором десериализатор может выйти из строя или работать неправильно
Спасибо