C'est un peu tard mais j'ai dû faire exactement la même chose aujourd'hui. Donc, d'après mes recherches et lorsque vous utilisez gson-2.0, vous ne voulez vraiment pas utiliser l'option registerTypeHierarchyAdapter mais plutôt la méthode plus banale registerTypeAdapter . Et vous n'avez certainement pas besoin de faire instanceofs ou écrire des adaptateurs pour les classes dérivées : un seul adaptateur pour la classe ou l'interface de base, à condition bien sûr que vous soyez satisfait de la sérialisation par défaut des classes dérivées. Quoi qu'il en soit, voici le code (paquetage et importations enlevés) (également disponible dans github ) :
La classe de base (interface dans mon cas) :
public interface IAnimal { public String sound(); }
Les deux classes dérivées, Cat :
public class Cat implements IAnimal {
public String name;
public Cat(String name) {
super();
this.name = name;
}
@Override
public String sound() {
return name + " : \"meaow\"";
};
}
Et le chien :
public class Dog implements IAnimal {
public String name;
public int ferocity;
public Dog(String name, int ferocity) {
super();
this.name = name;
this.ferocity = ferocity;
}
@Override
public String sound() {
return name + " : \"bark\" (ferocity level:" + ferocity + ")";
}
}
L'adaptateur IAnimalAdapter :
public class IAnimalAdapter implements JsonSerializer<IAnimal>, JsonDeserializer<IAnimal>{
private static final String CLASSNAME = "CLASSNAME";
private static final String INSTANCE = "INSTANCE";
@Override
public JsonElement serialize(IAnimal src, Type typeOfSrc,
JsonSerializationContext context) {
JsonObject retValue = new JsonObject();
String className = src.getClass().getName();
retValue.addProperty(CLASSNAME, className);
JsonElement elem = context.serialize(src);
retValue.add(INSTANCE, elem);
return retValue;
}
@Override
public IAnimal deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME);
String className = prim.getAsString();
Class<?> klass = null;
try {
klass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new JsonParseException(e.getMessage());
}
return context.deserialize(jsonObject.get(INSTANCE), klass);
}
}
Et la classe Test :
public class Test {
public static void main(String[] args) {
IAnimal animals[] = new IAnimal[]{new Cat("Kitty"), new Dog("Brutus", 5)};
Gson gsonExt = null;
{
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(IAnimal.class, new IAnimalAdapter());
gsonExt = builder.create();
}
for (IAnimal animal : animals) {
String animalJson = gsonExt.toJson(animal, IAnimal.class);
System.out.println("serialized with the custom serializer:" + animalJson);
IAnimal animal2 = gsonExt.fromJson(animalJson, IAnimal.class);
System.out.println(animal2.sound());
}
}
}
Lorsque vous exécutez le Test::main, vous obtenez le résultat suivant :
serialized with the custom serializer:
{"CLASSNAME":"com.synelixis.caches.viz.json.playground.plainAdapter.Cat","INSTANCE":{"name":"Kitty"}}
Kitty : "meaow"
serialized with the custom serializer:
{"CLASSNAME":"com.synelixis.caches.viz.json.playground.plainAdapter.Dog","INSTANCE":{"name":"Brutus","ferocity":5}}
Brutus : "bark" (ferocity level:5)
J'ai fait ce qui précède en utilisant le registerTypeHierarchyAdapter mais cela semblait nécessiter l'implémentation de classes de sérialiseur/désérialiseur personnalisées DogAdapter et CatAdapter, qui sont difficiles à maintenir chaque fois que l'on veut ajouter un nouveau champ à Dog ou à Cat.
0 votes
stackoverflow.com/q/19588020/3315914