【问题标题】:Handle two different JSON types in Android在 Android 中处理两种不同的 JSON 类型
【发布时间】:2019-04-03 15:57:20
【问题描述】:

我正在使用的 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 处理此问题,以便在处理响应时不会导致错误?

【问题讨论】:

    标签: java android json retrofit


    【解决方案1】:

    这与改造无关,而是与您使用的 JSON Deserializer 有关。 我猜您正在使用 GSON 适配器进行改造。那么您别无选择,只能为您的响应编写自定义反序列化器。

    让我给你看一个例子(在 Kotlin 中):

    1. 首先我们必须为响应创建一个基类。在 kotlin 中有一个很棒的构造,称为密封类。对于 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>
    
    1. 然后我们必须创建我们的反序列化器并将其注册到 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))
                ...
    
    
    1. 最后一步是检查错误响应的状态。
    //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
                                }
                            }
                        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-22
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      • 2019-07-01
      相关资源
      最近更新 更多