首页 > 解决方案 > 改造 2. 如果代码为 200,如何处理响应中的错误 JSON

问题描述

我正在使用 Vk Api,在 1 个场景中,我得到一个代码为 200 的响应对象,但它的主体是一个错误 JSON。

我想问你 - 是否有可能以某种方式从响应中获取错误对象并查看error_code从 Vk Api 返回的错误对象。

Retrofit 2在 android 和GsonConverterFactory.

我正在尝试做这样的事情:

class NetworkCheckerInterceptor(val networkChecker: NetworkChecker) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val requestBuilder = chain.request().newBuilder()
        if (!networkChecker.isConnected()) {
            throw NoNetworkConnectionException("No network connection.")
        }
        try {
            val response =  chain.proceed(requestBuilder.build())
            val error = Gson().fromJson(response.body()?.string(), Error::class.java)
            return response
        } catch (e: SocketTimeoutException) {
            throw SocketTimeoutException()
        } catch (e: UnknownHostException) {
            throw UnknownHostException()
        }
    }
}

但是当我尝试获取“错误”对象时出现错误。

json错误示例:

  {
  "error": {
    "error_code": 7,
    "error_msg": "Permission to perform this action is denied",
    "request_params": [
      {
        "key": "oauth",
        "value": "1"
      },
      {
        "key": "method",
        "value": "stats.get"
      },
      {
        "key": "timestamp_to",
        "value": "1542549195"
      },
      {
        "key": "month",
        "value": "month"
      },
      {
        "key": "group_id",
        "value": "56461699"
      },
      {
        "key": "v",
        "value": "5.87"
      },
      {
        "key": "interval",
        "value": "month"
      },
      {
        "key": "stats_groups",
        "value": "visitors"
      },
      {
        "key": "timestamp_from",
        "value": "1514757660"
      }
    ]
  }
}

我唯一关心"error_code": 7的是许可问题。

那么,即使我的响应代码是 200 ,我怎样才能得到这个对象呢?

标签: kotlinretrofit2androidgson

解决方案


您可以为 VK 网络响应创建基类

abstract class BaseVkResponse<T> {
    var response: T? = null
    var error: VKError? = null // (from vk sdk)
}

每个响应都应该扩展它。例如

class NewsItem {
    var type: String? = null
    var text: String? = null
    var date: Long? = null
}

class NewsPage {
    var items: List<NewsItem>? = null
    @SerializedName("nextFrom")
    var nextFrom: String? = null
}

class NewsResponse : BaseVkResponse<NewsPage>()

和改造界面看起来像

interface VkService {
    @GET("newsfeed.getRecommended")
    fun getNews(@Query("access_token") accessToken: String,
                @Query("v") apiVersion: String,
                @Query("count") count: Int?,
                @Query("start_from") startFrom: String?): Single<NewsResponse>
}

然后注册特殊类型适配器来解析 VkError 类型

internal class ErrorTypeAdapter : JsonDeserializer<VKError> {

    @Throws(JsonParseException::class)
    override fun deserialize(json: JsonElement,
                             typeOfT: Type,
                             context: JsonDeserializationContext
    ): VKError? {
        return try {
            VKError(JSONObject(json.toString()))
        } catch (e: JSONException) {
            null
        }
    }
}

val gson = GsonBuilder().apply {
    registerTypeAdapter(VKError::class.java, ErrorTypeAdapter())
}

如果响应的error字段不为空,您应该按照自己的意愿处理它。在其他情况下,您可以将其视为成功。


推荐阅读