Обработка двух разных типов JSON в Android - PullRequest
0 голосов
/ 03 апреля 2019

API, с которым я работаю, имеет два разных типа JSON в зависимости от того, заполнен объект или нет.Если он заполнен, это объект JSON, в противном случае это массив JSON, как мне поступить с этим в Retrofit?

Пусто "errors": []

Не пусто

"errors": {
        "licence": [
            "You have too many points on your licence"
        ],
        "general": [
            "An error occurred during your verification, please contact support"
        ]
    }

Как бы я справился с этим с помощью Retrofit, чтобы не вызывать ошибок при обработке ответа?

1 Ответ

0 голосов
/ 03 апреля 2019

Это не имеет ничего общего с модификацией, но с JSON Deserializer, который вы используете.Я полагаю, вы используете адаптер GSON для модернизации.Тогда у вас нет другого выбора, кроме как написать собственный десериализатор для вашего ответа.

Позвольте мне показать вам пример (на Kotlin):

  1. Сначала мы должны создать базовый класс дляответ.В котлине есть классная конструкция, называемая закрытым классом.Для Java я бы предложил создать два класса, которые представляют оба состояния (пустые и содержат данные) и наследуют от базового класса.
sealed class ErrorResponse {
    object Empty : ErrorResponse()
    data class ApiError(val licence: List<String>, val general: List<String>) : ErrorResponse()
}

//make sure you call function in the retrofit interface is set to the correct type
@GET("errors")
fun getErrorResponse() : Call<ErrorResponse>
Затем мы должны создать наш десериализатор и зарегистрировать его в экземпляре gson.Таким образом, мы можем сказать gson, как должны обрабатываться объекты типа n.
class ErrorResponseDeserializer : JsonDeserializer<ErrorResponse> {

    override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ErrorResponse {
        return when(json) {
            is JsonObject -> {
                context.deserialize<ErrorResponse.ApiError>(json, ErrorResponse.ApiError::class.java)
            }
            else -> ErrorResponse.Empty
        }
    }
}

//create gson instance and register the deserializer
val gson = GsonBuilder()
            .registerTypeAdapter(ErrorResponse::class.java, ErrorResponseDeserializer())
            .create()

//use own gson instance for the gson converter factory
Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create(gson))
            ...

Последний шаг - проверить, в каком состоянии находится ответ об ошибке.
//or use rxjava / coroutines etc for the response handling
override fun onResponse(call: Call<ErrorResponse>, response: Response<ErrorResponse>) {
                        val body = response.body()

                        when(body) {
                            is ErrorResponse.Empty -> {
                                //TODO handle empty array state
                            }
                            is ErrorResponse.ApiError -> {
                                //TODO handle api errors or whatever you want
                                val general = body.general //smart cast kotlin <3
                            }
                        }
                    }
...