Это идеальный сценарий / схема. Однако я не могу контролировать ответы 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 распознать эту структуру без необходимости вручную обрабатывать этот сценарий? Есть ли лучший способ сделать это? Я пропускаю какой-либо сценарий, в котором десериализатор может выйти из строя или работать неправильно

Спасибо

Ответы на вопрос(3)

Ваш ответ на вопрос