改造-在序列化过程中动态添加字段

时间:2018-11-07 17:28:07

标签: android gson retrofit

我当前在我的Android项目中使用Retrofit 2.3,并且最近我们使用的API已更新,因此在所有POST请求中,JSON正文中都必须包含"version":number。假设我们需要传递UserCredentials对象-之前的请求主体只是使用GSON转换器序列化了,看起来像这样

{"username":"myUsername", "password":"myPassword"}

现在它必须具有其他“版本”字段:

{"username":"myUsername", "password":"myPassword", "version":1}

我已经搜索了几个小时,如何设置自定义转换器工厂以进行改装,但是我发现的全部是如何从序列化中排除某些字段。我知道我可以简单地将"version"字段添加到我的所有POJO中,但是我发现这种方法“肮脏”,因为它将仅在向服务器发送数据期间使用。

以前有人做过这样的事吗?

2 个答案:

答案 0 :(得分:1)

我做到了,但并非完全按照您想要的方式进行,您可以创建BaseRequest POJO类,在其中您可以使用版本号,然后将该类扩展到您正在使用的其他POJO类:

Expected Output:
OrderedDict([('108', ['0.0']), ('101', ['0.0']), ('13', ['0.0']), ('104', 
['0.0']), ('105', ['0.0']), ('109', ['0.0']), ('107', ['1.0']), ('102', 
['1.0']), ('106', ['1.0']), ('99', ['1.0']), ('103', ['1.0']), ('100', 
['1.0']), ('14', ['8.0'])])

将此基本POJO类扩展到其他POJO类以使用这样的版本号:

class BaseRequest{
@SerializedName("version")
public int version= 0;
 }

此方法有很多好处,例如,如果您在API中需要一个字段,那么就不需要更改所有api。您只需在baserequest中添加一个字段即可实现。

答案 1 :(得分:0)

使用OkHTTP客户端的自定义拦截器解决了此问题。因此,我创建了自定义拦截器,该拦截器将分析传出请求并在满足特定条件时更改其主体JSON数据。

okHttpClientBuilder.addInterceptor(CustomInterceptor(1))

像魅力一样工作!

import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import okio.Buffer
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException

class CustomInterceptor (private val version: Int): Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        var request = chain.request()
        val requestBody = request.body()
        val subtype = requestBody?.contentType()?.subtype()
        if(subtype != null
                && subtype.contains("json")) {
            val bodyWithToken = addVersionParamToJSONBody(requestBody)
            if(null != bodyWithToken){
                val requestBuilder = request.newBuilder()
                request = requestBuilder
                        .post(bodyWithToken)
                        .build()
            }
        }
        return chain.proceed(request)
    }

    private fun addVersionParamToJSONBody(requestBody: RequestBody?) : RequestBody? {
        val customRequest = bodyToString(requestBody)
        return try{
            val jsonObject = JSONObject(customRequest)
            jsonObject.put("version", version)
            RequestBody.create(requestBody?.contentType(), jsonObject.toString())
        } catch (e: JSONException){
            e.printStackTrace()
            null
        }
    }

    private fun bodyToString(requestBody: RequestBody?): String{
        return try {
            val buffer = Buffer()
            requestBody?.writeTo(buffer)
            buffer.readUtf8()
        } catch (e: IOException){
            e.printStackTrace()
            ""
        }
    }
}