Модификация 2, обрабатывающая динамические обратные вызовы API JSONArray или JSONObject - PullRequest
0 голосов
/ 03 апреля 2019

Мой JSON ответ сервера обычно такой: [{}] (Массив объектов), за исключением того, что они устанавливают ошибки для возврата объекта {} Так что, когда я вызываю, конечно, если есть проблема с ответом ион возвращает объект Я получаю следующую ошибку:

Expected BEGIN_ARRAY but was BEGIN_OBJECT

В моем коде я ожидаю ArrayList и получаю объект (хотя я не уверен, как с этим справиться? Когда я получаю объектэто означает, что есть проблема с вызовом API, и мне нужно разобраться с тем, что ответили в объекте.

Пример ответа от API:

{
  "StatusCode": -7,
  "StatusMessage": "Invalid",
  "Details": ""
}

Интерфейс APIService ниже:

interface MyAPIService {
    @GET("RequestByToken")
    fun getCurrentRequestAsync(
        @Query("token") token: String
    ): Deferred<List<CurrentResponse>>

    companion object {
        operator fun invoke(
            connectivityInterceptor: ConnectivityInterceptor
        ): MyAPIService {
            val requestInterceptor = Interceptor { chain ->

                //Creates a new URL adding in the CONST'S
                val url = chain.request()
                    .url()
                    .newBuilder()
                    .addQueryParameter("format", FORMAT)
                    .build()

                //Creates new Request with the new URL
                val request = chain.request()
                    .newBuilder()
                    .url(url.toString())
                    .build()

                println(request)
                return@Interceptor chain.proceed(request)
            }

            //Intercepts each http call and adds the url above automatically
            val okHttpClient = OkHttpClient.Builder()
                .addInterceptor(requestInterceptor)
                .addInterceptor(connectivityInterceptor)
                .build()

            return Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(BASE_URL)
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(MyAPIService::class.java)
        }
    }
}

1 Ответ

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

Вы можете использовать JsonElement в качестве типа возврата и определить, является ли он JsonObject или JsonArray, используя метод isJsonArray(), и оттуда вы можете просто десериализовать его.

Вы также можете сделать это в общем виде, создать класс, представляющий как ответы вашего списка, так и ответы объекта, и написать адаптер типа для этого типа:

 sealed class SampleResponse {
    data class ArraySampleResponse(val currentResponses: List<CurrentResponse>) : SampleResponse()
    data class SimpleSampleResponse(val currentResponse: CurrentResponse) : SampleResponse()
}
class CustomDeserializer : JsonDeserializer<SampleResponse> {

    @Throws(JsonParseException::class)
    fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): SampleResponse {
        if (json.isJsonObject()) {
            // parse as object and create your object
            return SampleResponse.SimpleSampleResponse() 
        } else if (json.isJsonArray()) {
            // parse as array and create your object
            return SampleResponse.ArraySampleResponse()

        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...