In daily development, the common data transfer protocol format for network requests is usually fixed, such as JSON or XML. There are some exceptions, however, and having multiple formats in a project can be a headache for Android developers.

Retrofit-converter. Factory Conversion Factory

Retrofit is a common and powerful web request framework that converts a Bean to a RequestBody and a ResponseBody to a Bean via Converter. The official also provides some conversion factories for us to develop quickly: Retrofit-Converters

Importing dependent dependencies

implementation 'com. Squareup. Retrofit2: retrofit: 2.6.2'
implementation 'com. Squareup. Retrofit2: converter - gson: 2.6.2'
implementation 'com. Squareup. Retrofit2: converter - simplexml: 2.6.2'
Copy the code

The version number can be replaced with the latest version. Tip: SimpleXml has been officially deprecated and is officially recommended to use JAXB, but testing JAXB at the time reported errors. converter-jaxb

Create the ConverterFormat enumeration class

/** * How to parse data * JSON or XML */
enum class ConverterFormat {
    JSON,
    XML
}
Copy the code

Declare RequestConverter annotations

@Target(
    AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class RequestConverter(val format: ConverterFormat = ConverterFormat.JSON)
Copy the code

The default format is JSON.

Declare ResponseConverter annotations

@Target(
    AnnotationTarget.FUNCTION
)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
annotation class ResponseConverter(val format: ConverterFormat = ConverterFormat.JSON)
Copy the code

The default format is JSON.

Custom JsonOrXmlConverterFactory

class JsonOrXmlConverterFactory private constructor() : Converter.Factory(a){
    private var jsonFactory: Converter.Factory
    private var xmlFactory: Converter.Factory

    init {
        val gson = GsonBuilder()
            .serializeNulls()
            .create()
        jsonFactory = GsonConverterFactory.create(gson)

        xmlFactory = SimpleXmlConverterFactory.createNonStrict()
    }

    companion object {
        fun create() = JsonOrXmlConverterFactory()
    }

    override fun requestBodyConverter(
        type: Type,
        parameterAnnotations: Array<Annotation>,
        methodAnnotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<*, RequestBody>? {
        for (annotation in methodAnnotations) {
            if (annotation is RequestConverter) {
                if (annotation.format == ConverterFormat.JSON) {
                    return jsonFactory.requestBodyConverter(
                        type,
                        parameterAnnotations,
                        methodAnnotations,
                        retrofit
                    )
                } else if (annotation.format == ConverterFormat.XML) {
                    return xmlFactory.requestBodyConverter(
                        type,
                        parameterAnnotations,
                        methodAnnotations,
                        retrofit
                    )
                }
            }
        }
        return jsonFactory.requestBodyConverter(
            type,
            parameterAnnotations,
            methodAnnotations,
            retrofit
        )
    }

    override fun responseBodyConverter(
        type: Type,
        annotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<ResponseBody, *>? {
        for (annotation in annotations) {
            if (annotation is ResponseConverter) {
                if (annotation.format == ConverterFormat.JSON) {
                    return jsonFactory.responseBodyConverter(type, annotations, retrofit)
                } else if (annotation.format == ConverterFormat.XML) {
                    return xmlFactory.responseBodyConverter(type, annotations, retrofit)
                }
            }
        }
        return jsonFactory.responseBodyConverter(type, annotations, retrofit)
    }
}
Copy the code

If no annotations are found, the JSON format is used.

Method of use

  1. Create the Retrofit by adding the JsonOrXmlConverterFactory addConverterFactory instance
fun init() {
    val retrofitBuilder = Retrofit.Builder()
    	.addConverterFactory(JsonOrXmlConverterFactory.create())
    val retrofit = retrofitBuilder.build()
    val apiService = retrofit.create(ApiService::class.java)
}
Copy the code
  1. Add annotations to the interface
@POST
@RequestConverter(ConverterFormat.XML)
@ResponseConverter(ConverterFormat.JSON)
@Headers("Connection: Close")
fun netRelayCtrl(@Url url: String, @Body bean: NetRelayCtrlBean): Observable<NetRelayCtrlResultBean>
Copy the code

Without RequestConverter and ResponseConverter annotations, JSON parsing is used by default. If there are mistakes, but also hope to correct.