所以,RTTAF 方法是朝着正确的方向推进,但它希望我有一个字段来指示我正在使用的子类型。在我的具体情况下,我有这些子类型的子类型和子类型。这就是我最终要做的:
更新:Created Github gist
注意:在我的测试项目(如下)中,我使用 GSON 和 Lombok 进行注释。
类型工厂
public class CustomTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create (final Gson gson, final TypeToken<T> type) {
if (type.getRawType () != SuperType.class)
return null;
final TypeAdapter<T> delegate = gson.getDelegateAdapter (this, type);
return new TypeAdapter<T> () {
@Override
public void write (final JsonWriter jsonWriter, final T t) throws IOException {
delegate.write (jsonWriter, t);
}
@Override
public T read (final JsonReader jsonReader) throws IOException, JsonParseException {
JsonElement tree = Streams.parse (jsonReader);
JsonObject object = tree.getAsJsonObject ();
if (object.has ("a"))
return (T) readTypeA (tree, object.getAsJsonObject ("a"));
if (object.has ("b"))
return (T) readTypeB (tree, object.getAsJsonObject ("b"));
throw new JsonParseException ("Cannot deserialize " + type + ". It is not a valid SuperType JSON.");
}
private TypeA readTypeA (final JsonElement tree, final JsonObject a) {
if (a.has ("aa"))
return gson.getDelegateAdapter (CustomTypeAdapterFactory.this, TypeToken.get (TypeA_A.class)).fromJsonTree (tree);
if (a.has ("ab"))
return gson.getDelegateAdapter (CustomTypeAdapterFactory.this, TypeToken.get (TypeA_B.class)).fromJsonTree (tree);
if (a.has ("ac"))
return gson.getDelegateAdapter (CustomTypeAdapterFactory.this, TypeToken.get (TypeA_C.class)).fromJsonTree (tree);
throw new JsonParseException ("Cannot deserialize " + type + ". It is not a valid TypeA JSON.");
}
private TypeB readTypeB (final JsonElement tree, final JsonObject b) {
if (b.has ("ba"))
return gson.getDelegateAdapter (CustomTypeAdapterFactory.this, TypeToken.get (TypeB_A.class)).fromJsonTree (tree);
if (b.has ("bb"))
return gson.getDelegateAdapter (CustomTypeAdapterFactory.this, TypeToken.get (TypeB_B.class)).fromJsonTree (tree);
if (b.has ("bc"))
return gson.getDelegateAdapter (CustomTypeAdapterFactory.this, TypeToken.get (TypeB_C.class)).fromJsonTree (tree);
throw new JsonParseException ("Cannot deserialize " + type + ". It is not a valid TypeB JSON.");
}
};
}
}
SuperType.java
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class SuperType {
@SerializedName ("ct")
protected long creationTime;
@SerializedName ("id")
protected String id;
}
Type_A 在其级别中没有额外的数据,但确实有一些常见的行为(为了简单起见,这里省略了方法,因为它们与解析无关)。
TypeA.java
@Getter
@Setter
@EqualsAndHashCode (callSuper = true)
@ToString (callSuper = true)
public class TypeA extends SuperType {}
TypeA_A.java
@Getter
@Setter
@EqualsAndHashCode (callSuper = true)
@ToString(callSuper = true)
public class TypeA_A
extends TypeA {
@SerializedName ("a")
protected AA aValue;
@ToString
private static class AA {
@SerializedName ("aa")
private String aaValue;
}
}
其他 Type_A 子代与 TypeA_A 非常相似。
Type_B 稍微复杂一些,因为它有自己的数据和行为(再次为简单起见,省略了):
TypeB.java
@Getter
@Setter
@EqualsAndHashCode (callSuper = true)
@ToString (callSuper = true)
public class TypeB extends SuperType {
// no member declared here
protected static abstract class B {
@SerializedName ("b1")
protected String b1Value;
@SerializedName ("b2")
protected String b2Value;
}
}
Type_BA.java
@Getter
@Setter
@EqualsAndHashCode (callSuper = true)
@ToString (callSuper = true)
public class TypeB_A
extends TypeB {
@SerializedName ("b")
protected BA bValue;
@ToString
private static class BA extends B {
@SerializedName ("ba")
private String baValue;
}
}
TypeB_B.java
@Getter
@Setter
@EqualsAndHashCode (callSuper = true)
@ToString (callSuper = true)
public class TypeB_B
extends TypeB {
@SerializedName ("b")
protected BB bValue;
@ToString
private static class BB extends B {
@SerializedName ("bb")
private String bbValue;
@SerializedName ("bb1")
private String bb1Value;
}
}
这里可能有一些拼写错误,因为我必须更改实际的类型名称和值,但我将创建一个基本的 java 代码示例并将发布到 Github。
感谢@Jesse Wilson 和@Argyle 帮助我指明了正确的方向。