Java 改装Gson自定义json通用转换器
我以前在几个项目上进行过改造,但现在我想做一些稍微不同的事情。我正在调用一个api,该api将我的响应封装在类似以下的结构中:Java 改装Gson自定义json通用转换器,java,android,json,gson,retrofit2,Java,Android,Json,Gson,Retrofit2,我以前在几个项目上进行过改造,但现在我想做一些稍微不同的事情。我正在调用一个api,该api将我的响应封装在类似以下的结构中: { // only for demo purposes. Probably errors and data will never be populated together "body": { "errors": { "username": [ "Username is too short", "Username
{ // only for demo purposes. Probably errors and data will never be populated together
"body": {
"errors": {
"username": [
"Username is too short",
"Username already exists"
]
},
"data": {
"message": "User created."
}
}
}
我正在尝试将所有这些转换为一个泛型类,该类将为我包装该响应。我想的是
public class ApiResponse<T> {
private T data;
private Map<String, List<String>> errors;
public ApiResponse(T data, Map<String, List<String>> errors) {
this.data = data;
this.errors = errors;
}
}
然后在构建我的改造客户机时
public static Retrofit getClient() {
if (okHttpClient == null) {
initOkHttp();
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(ApiResponse.class, new ApiResponseDeserializer<>(......) // PROBLEM
.create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(Const.API_BASE_URL)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
但是,如何使用知道如何将响应转换为
ApiResponse
的通用Gson类型适配器创建一个通用改装实例呢?并且知道响应中的数据
属性应转换为类型为RegisterResponseData
..的对象。当您在改型的客户端中指定返回类型时,它将作为类型传递给改型的转换器,然后Gson接收该类型,该类型将成为您的ApiResponse
。从这一点上,Gson将理解数据
属于RegisterResponseData类型
,并将生成您的模型对象
只需在不使用APIResponsedSerializer
的情况下尝试它,您就会看到它正在工作
编辑:
在评论中回答您的其他问题:
如果您想跳过json中的“body”对象,可以这样编写包装器对象:
公共类响应{
@序列化名称(“正文”)
私人蜂巢体;
公众回应({
}
公共ApiResponse(ApiData机构){
这个身体=身体;
}
}
公共类apiesbody{
@SerializedName(“数据”)
私有T数据;
@SerializedName(“错误”)
私有映射错误;
公共ApiResponseBody(){
}
公共ApiResponseBody(T数据、映射错误){
这个数据=数据;
这个。错误=错误;
}
}
并以惯常的方式使用它
@POST(“用户/注册”)
单个寄存器(@Body RegisterRequest请求);
Ohh,事实上是的。。有趣的我以为我必须手动提供转换的泛型类,但似乎我没有。。你知道如何跳过在ApiResponse中放置Body对象吗?我可能会继续使用我的APIResponsedSerializer
来访问json
中“body”标签所引用的对象,然后尝试上下文。反序列化
。要跳过body,可以编写包装器对象。我将在回答中解释我以前也使用过这种“包装器对象”技术,但我想完全跳过它,这样我就不必额外调用ApiResponse
的getBody()
方法来实际获取我的数据和错误。。我将使用我的APIResponsedSerializer
执行最终的JsonObject body=JsonObject.getAsJsonObject(“body”)
然后返回上下文。反序列化(body,typeOfT)
使我的错误和数据直接进入ApiResponse
,而不使用包装器对象。再次非常感谢!它比我想象的要简单得多,但是在任何地方都找不到文档化的泛型内容,因此我不需要额外调用ApiResponse的getBody(),您可以编写方法来省略对getBody()的调用public t getData(){return getBody().getData()}
public static Retrofit getClient() {
if (okHttpClient == null) {
initOkHttp();
}
Gson gson = new GsonBuilder()
.registerTypeAdapter(ApiResponse.class, new ApiResponseDeserializer<>(......) // PROBLEM
.create();
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(Const.API_BASE_URL)
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
return retrofit;
}
@POST("users/signup")
Single<ApiResponse<RegisterResponseData>> register(@Body RegisterRequest request);