Analisador de resposta Json para matriz ou objeto
Estou escrevendo uma biblioteca para consumir uma API Json e estou enfrentando um problema de design ao usar o Gson como a biblioteca de análise.
Um dos pontos de extremidade retorna umarray
de objetos se tudo correr bem assim:
[
{
"name": "John",
"age" : 21
},
{
"name": "Sarah",
"age" : 32
},
]
No entanto, o esquema de erro para todos os terminais na API é um jsonobject
em vez de uma matriz.
{
"errors": [
{
"code": 1001,
"message": "Something blew up"
}
]
}
O problema surge ao modelar isso em POJOs. Como o esquema de erro é comum a todos os pontos de extremidade da API, decidi ter um resumoApiResponse
classe que mapeará apenas o atributo de erros
public abstract class ApiResponse{
@SerializedName("errors")
List<ApiResponseError> errors;
}
public class ApiResponseError {
@SerializedName("code")
public Integer code;
@SerializedName("message")
public String message;
}
Agora eu gostaria de herdar deApiResponse
ter o mapeamento de erro "de graça" e uma resposta de POJO por terminal da API. No entanto, o objeto json de nível superior para esta resposta é uma matriz (se o servidor conseguir executar a solicitação), portanto, não posso criar uma nova classe para mapeá-la como gostaria.
Eu decidi ainda criar uma classe estendendoApiResponse
:
public class ApiResponsePerson extends ApiResponse {
List<Person> persons;
}
E implementou um desserializador personalizado para analisar corretamente o json, dependendo do tipo do objeto de nível superior e configurá-lo para o campo correto na seguinte classe:
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'");
}
}
Que eu adicionarei ao Gson
Gson gson = new GsonBuilder()
.registerTypeAdapter(ApiResponsePerson.class, new DeserializerApiResponsePerson())
.create();
Existe alguma maneira de modelar esses POJOs e fazer com que o Gson reconheça essa estrutura sem precisar lidar manualmente com esse cenário? Existe alguma maneira melhor de conseguir isso? Estou perdendo algum cenário em que o desserializador pode falhar ou não funcionar conforme o esperado?
obrigado