Ecco l'implementazione completa basata sulla risposta incompleta fornita da @ user1556622 e la discussione in code.google.com/p/google-gson/issues/detail?id=43.
Come risultato, è possibile serializzare l'elenco degli oggetti astratti Field
e deserializzare senza problemi indipendentemente dall'implementazione concreta dello specifico Field
e dalla profondità della gerarchia.
class MyClass { //class which we would like to serialiaze/deserialize
List<Field> fields; //field is an hierarchy of classes
}
/**
* Purpose of this adapter is simple:
* 1) put during serialization in all Field objects additional property describing class
* 2) during deserialization invoke (based on class info) necessary deserializer to create class
*/
public class FieldTypeAdapterFactory implements TypeAdapterFactory {
private static final String CLASS_META_KEY="clz";
Gson gson;
TypeToken<?> type;
TypeAdapter<Field> fieldAdapter;
TypeAdapter<JsonElement> elementAdapter;
TypeAdapterFactory taf;
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!Field.class.isAssignableFrom(type.getRawType()))
return null; // this class only serializes 'Field' and its subtypes
this.type=type;
this.gson=gson;
this.taf=this;
fieldAdapter = gson.getDelegateAdapter(taf, TypeToken.get(Field.class));
elementAdapter = gson.getAdapter(JsonElement.class);
TypeAdapter<T> result = new FieldTypeAdapter<T>();
result.nullSafe();
return result;
}
class FieldTypeAdapter<T> extends TypeAdapter<T> {
public FieldTypeAdapter() {
}
@Override
public void write(JsonWriter out, Object value) throws IOException {
if(value instanceof Field) {
JsonObject object = fieldAdapter.toJsonTree((Field)value).getAsJsonObject();
object.addProperty(CLASS_META_KEY, value.getClass().getCanonicalName());
elementAdapter.write(out, object);
}
else {
elementAdapter.write(out, (JsonElement) value);
}
}
@Override
public T read(JsonReader in) throws IOException {
JsonObject object = elementAdapter.read(in).getAsJsonObject();
if (object.has(CLASS_META_KEY)) {
String className=object.get(CLASS_META_KEY).getAsString();
try {
Class<?> clz = Class.forName(className);
TypeAdapter<?> adapter = gson.getDelegateAdapter(taf, TypeToken.get(clz));
return (T) adapter.fromJsonTree(object);
}
catch (Exception e) {
return (T)fieldAdapter.fromJsonTree(object);
}
}
else
return (T)elementAdapter.fromJsonTree(object);
}
}
}
Registrazione di fabbrica:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new FieldTypeAdapterFactory())
.create();
capito che c'è un problema generale http://code.google.com/p/google-gson/issues/detail?id=43 – Asim
Bel lavoro Asim. Puoi per favore pubblicare una risposta alla domanda tu stesso e quindi accettare quella risposta in modo che possiamo chiudere questa domanda? Inoltre, è necessario accettare le risposte alle domande precedenti se risolvono il problema. – Zecas
@Kev Per favore riaprire questa domanda. Ovviamente è stato rilevante per almeno 8 persone che hanno dato un upvote, incluso me (la nona persona). – Guy