retrofit 同时支持 xml 和 json

retrofit 解析 json 是很简单的,但是,偶尔,只是偶尔,你也可能遇到解析 xml 的需求,而且最怕的是不同的接口返回的类型不一样,一个返回 json 一个 返回 xml,如何兼容?使用两个 retrofit 实例还是?本文将介绍一种更简单的办法,自定义 convert

平时,我们可能这样写代码:

Retrofit.Builder()
    .baseUrl(baseUrl)
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .build()

这里 GsonConverterFactory.create() 指定了使用 Gson 解析数据,我们完全可以自定义一个 convert ,类似这样:

import androidx.annotation.NonNull
import okhttp3.ResponseBody
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.simplexml.SimpleXmlConverterFactory
import top.kpromise.utils.IJson.getGson
import java.lang.reflect.Type

class SmartConverter : Converter.Factory() {
    private val xmlFactory: Converter.Factory = SimpleXmlConverterFactory.create()
    private val jsonFactory: Converter.Factory = GsonConverterFactory.create(getGson())
    override fun responseBodyConverter(@NonNull type: Type,
                                       annotations: Array<Annotation>,
                                       @NonNull retrofit: Retrofit): Converter<ResponseBody, *>? {
        for (annotation in annotations) {
            if (annotation !is ContentType) {
                continue
            }
            val value = annotation.value
            if (DataType.XML == value) {
                return xmlFactory.responseBodyConverter(type, annotations, retrofit)
            }
        }
        return jsonFactory.responseBodyConverter(type, annotations, retrofit)
    }

    companion object {
        fun create(): SmartConverter {
            return SmartConverter()
        }
    }
}

注解类 ContentType.kt 是这样子的:

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class ContentType(val value: DataType = DataType.JSON) {

}

enum class DataType(private val contentType: String) {

    JSON("json"),
    XML("xml");

    fun contentType(): String {
        return contentType
    }
}

在需要的接口上可以这样子:

@GET("/xxx/xxx")
@ContentType(DataType.XML)
fun autoReg(@Query("cardNo") cardNo: String?): Call<AutoReg>

这里 @ContentType(DataType.XML) 指定了该接口返回的数据是 xml 的,不加这个注解 或者 加 @ContentType(DataType.JSON)  则是 JSON,至于 xml 解析,我们下篇再说。

本博客若无特殊说明则由 full-stack-trip 原创发布
转载请点名出处:全栈之旅 > retrofit 同时支持 xml 和 json
本文地址:https://www.kpromise.top/retrofit-support-xml-and-json/

发表评论

电子邮件地址不会被公开。 必填项已用*标注