Java 可以避免JSON包装器';单输入';地图?

Java 可以避免JSON包装器';单输入';地图?,java,json,rest,gson,retrofit,Java,Json,Rest,Gson,Retrofit,在使用Refught2为REST接口编写存根时,我看到的一种常见模式是,实际参数通常需要使用一个带有单个条目的映射(或者更糟糕的是,使用一个包含单个字段的类的包装类)进行包装 典型的JSON有效负载看起来像{“idontcareautthis”:{//Data我实际上想要…。有没有办法去掉这个相对无用的外壳?我觉得奇怪的是,我所有的REST方法都有一个返回类型的映射。你不需要映射。你只需要编写你自己的JSON反序列化程序。比如说,你有以下JSON,其中你不需要根对象单键: { "idon

在使用Refught2为REST接口编写存根时,我看到的一种常见模式是,实际参数通常需要使用一个带有单个条目的映射(或者更糟糕的是,使用一个包含单个字段的类的包装类)进行包装


典型的JSON有效负载看起来像
{“idontcareautthis”:{//Data我实际上想要…
。有没有办法去掉这个相对无用的外壳?我觉得奇怪的是,我所有的REST方法都有一个返回类型的映射。

你不需要映射。你只需要编写你自己的JSON反序列化程序。比如说,你有以下JSON,其中你不需要根对象单键:

{
    "idontcareaboutthis": {
        "foo": 1,
        "bar": 2
    }
}
那么JSON反序列化程序可能如下所示:

final类响应JSON反序列化器
实现JsonDeserializer{
私人最终Gson支持Gson;
专用响应JSON反序列化器(最终Gson备份Gson){
this.backingGson=backingGson;
}
静态JsonDeserializer GetResponseJSON反序列化程序(最终Gson backingGson){
返回新的响应JSON反序列化器(backingGson);
}
@凌驾
公共T反序列化(最终JsonElement json、最终类型类型、最终JsonDeserializationContext)
抛出JsonParseException{
final JsonObject root=json.getAsJsonObject();
final Set entries=root.entrySet();
final int propertyCount=entries.size();
如果(propertyCount!=1){
抛出新的JsonParseException(“需要一个属性根对象,但得到了一个带有“+propertyCount+”属性的对象”);
}
final Entry internal=entries.iterator().next();
//由于递归,无法在此使用上下文。反序列化
返回backingGson.fromJson(inner.getValue(),type);
}
}
请注意上面的反序列化程序是如何提取根对象项的,以及它是如何将反序列化过程委托给另一个Gson实例的。现在,您必须创建一个Gson实例,该实例知道
IDONTCAREAOUTTHIS
属性

private static final Gson registerybackinggson=new GsonBuilder()
//这里需要什么
.create();
私有静态最终Gson注册表Gson=new GsonBuilder()
.registerTypeAdapter(FooBarResponse.class,GetResponseJSON反序列化器(registryBackingGson))
//在这里像上面一样添加另一个响应类,但不注册其他类型-它们必须在registryBackingGson中注册
.create();
registryGson
要求枚举所有响应类或注册特定的类型层次结构。如果第一种情况对您来说不太方便,并且您可以更改响应类源代码,您可以添加一个特殊的标记接口以注册整个类型层次结构。例如:

private static final Gson registerybackinggson=new GsonBuilder()
//这里需要什么
.create();
私有静态最终Gson注册表Gson=new GsonBuilder()
.registerTypeHierarchyAdapter(IResponse.class,getResponseJsonDeserializer(registryBackingGson))
//无需在此处添加其他“响应”类-它们只需实现marker接口
.create();
数据传输对象:

final类FooBarResponse{
//对于传入的DTO类,“final”修饰符是一种合理的习惯,但基本常量是由编译器内联的。
//抑制内联是一个简单的解决方法,可以让javac认为它不是一个真正的常量。
//然而,这是代码风格的问题,这只是一个示例。
私有最终整数foo=constOf(0);
专用最终整型条=常数(0);
int getFoo(){
返回foo;
}
int getBar(){
返回杆;
}
//我们在作弊。。。
专用静态整数常量(最终整数i){
返回i;
}
}
如果您希望使用标记接口并注册整个类型层次结构

接口i响应{
}
最后一节课食物反应
实现我的响应{
...
以及它的工作原理:

final FooBarResponse fooBar = registryGson.fromJson(JSON, FooBarResponse.class)
out.println(fooBar.getFoo()); // 1
out.println(fooBar.getBar()); // 2
改装适配器:

final Retrofit retrofit = new Retrofit.Builder()
        // ...
        .addConverterFactory(GsonConverterFactory.create(registryGson))
        .build();
因此,您的改型基本接口方法可以返回
FooBar
/etc类实例,而不是映射。

使用converts.1.2.
reformation.Builder.addConverterFactory(Converter.Factory)
3.(如果使用Gson)创建一个类似于GsonConverterFactory.java的文件,添加您的自定义逻辑。