マップは必要ありません。独自のJSONデシリアライザを作成できます。あなたがキー単一のルートオブジェクトを必要としない以下のJSONを持っている、のは、言ってみましょう:
{
"idontcareaboutthis": {
"foo": 1,
"bar": 2
}
}
次にJSONのデシリアライザは、次のようになります。デシリアライザは、上記の抽出方法
final class ResponseJsonDeserializer<T>
implements JsonDeserializer<T> {
private final Gson backingGson;
private ResponseJsonDeserializer(final Gson backingGson) {
this.backingGson = backingGson;
}
static <T> JsonDeserializer<T> getResponseJsonDeserializer(final Gson backingGson) {
return new ResponseJsonDeserializer<>(backingGson);
}
@Override
public T deserialize(final JsonElement json, final Type type, final JsonDeserializationContext context)
throws JsonParseException {
final JsonObject root = json.getAsJsonObject();
final Set<Entry<String, JsonElement>> entries = root.entrySet();
final int propertyCount = entries.size();
if (propertyCount != 1) {
throw new JsonParseException("Expected a single property root object, but got an object with " + propertyCount + " properties");
}
final Entry<String, JsonElement> inner = entries.iterator().next();
// Can't use context.deserialize here due to recursion
return backingGson.fromJson(inner.getValue(), type);
}
}
注意他のGsonインスタンスにデシリアライズプロセスを委譲する方法について説明します。これで、idontcareaboutthis
プロパティを認識しているGsonインスタンスを作成する必要があります。
private static final Gson registryBackingGson = new GsonBuilder()
// whatever necessary here
.create();
private static final Gson registryGson = new GsonBuilder()
.registerTypeAdapter(FooBarResponse.class, getResponseJsonDeserializer(registryBackingGson))
// add another response classes here like the above, but do not register other types - they must be registered in registryBackingGson
.create();
registryGson
すべての応答クラスを列挙したり、特定のタイプの階層を登録するのいずれかが必要です。最初のケースがそれほど便利ではなく、レスポンスクラスのソースコードを変更できる場合は、タイプマーカー全体を登録するための特別なマーカーインターフェイスを追加することができます。言って、このような何か:
private static final Gson registryBackingGson = new GsonBuilder()
// whatever necessary here
.create();
private static final Gson registryGson = new GsonBuilder()
.registerTypeHierarchyAdapter(IResponse.class, getResponseJsonDeserializer(registryBackingGson))
// no need to add another "response" classes here - they just must implement the marker interface
.create();
データ転送オブジェクト:
final class FooBarResponse {
// The `final` modifier is a reasonable habit for incoming DTO classes, but primitive constants are inlined by the compiler.
// Suppressing the inlining can be done be a simple workaround to make javac think that it's not a real constant.
// However, it's a matter of your code style, and this is just an example.
private final int foo = constOf(0);
private final int bar = constOf(0);
int getFoo() {
return foo;
}
int getBar() {
return bar;
}
// We're cheating...
private static int constOf(final int i) {
return i;
}
}
そして、あなたはマーカーインターフェイスを好むと
interface IResponse {
}
final class FooBarResponse
implements IResponse {
...
を全タイプの階層を登録するかのそして、どのようにそれが動作します:
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クラスのインスタンスではなく、マップを返すことができます。
コンバーターを使用します。 1. http://square.github.io/retrofit/#restadapter-configuration 2. 'Retrofit.Builder.addConverterFactory(Converter.Factory factory)' 3.(Gsonを使用している場合)GsonConverterFactoryに似たファイルを作成します。カスタム論理を追加するjava。 – Sangharsh