Android 改装-在序列化过程中动态添加字段
我目前正在我的Android项目中使用改型2.3,最近我们使用的API被更新,因此它需要在所有POST请求的JSON正文中包含Android 改装-在序列化过程中动态添加字段,android,gson,retrofit,Android,Gson,Retrofit,我目前正在我的Android项目中使用改型2.3,最近我们使用的API被更新,因此它需要在所有POST请求的JSON正文中包含“version”:number。所以,假设我们需要传递UserCredentials对象——之前请求的主体只是使用GSON转换器序列化的,如下所示 {“用户名”:“我的用户名”,“密码”:“我的密码”} 现在它必须有额外的“版本”字段: {“用户名”:“我的用户名”,“密码”:“我的密码”,“版本”:1} 我在谷歌上搜索了几个小时如何设置定制转换器工厂进行改造,但我所发
“version”:number
。所以,假设我们需要传递UserCredentials对象——之前请求的主体只是使用GSON转换器序列化的,如下所示
{“用户名”:“我的用户名”,“密码”:“我的密码”}
现在它必须有额外的“版本”字段:
{“用户名”:“我的用户名”,“密码”:“我的密码”,“版本”:1}
我在谷歌上搜索了几个小时如何设置定制转换器工厂进行改造,但我所发现的只是如何从序列化中排除某些字段。我知道我可以简单地将“version”
字段添加到我的所有POJO中,但我发现这种方法“脏”,因为它只在向服务器发送数据时使用
以前有人做过类似的事情吗?我做过,但不是按照您想要的方式,您可以创建BaseRequest POJO类,在该类中可以使用版本号,并将该类扩展到您正在使用的其他POJO类,如下所示:
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
将此基本POJO类扩展到其他POJO类以使用如下版本号:
class BaseRequest{
@SerializedName("version")
public int version= 0;
}
class UserRequest extends BaseRequest{
@SerializedName("username")
public String userName = "";
@SerializedName("password")
public String password = "";
}
这种方法有很多好处,比如如果您的API中还需要一个字段,那么就不需要更改所有API。您只需在baserequest中添加一个字段即可实现这一点。使用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()
""
}
}
}
我不想这样做,因为有几个因素:“版本”只在API调用期间使用,我更喜欢组合而不是继承。你可以公开你的改型API方法声明,只是为了澄清一下你是如何发送登录数据的吗?根据你的回答,你正在使用Kotlin或其他东西。也许你可以在你的问题中更新标签。我创建了基于Java的解决方案,以防您也尝试应用该解决方案。