Java 改装Gson自定义json通用转换器

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

我以前在几个项目上进行过改造,但现在我想做一些稍微不同的事情。我正在调用一个api,该api将我的响应封装在类似以下的结构中:

{ // 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);