java json abstract-class gson

java - Deserializar una clase abstracta en Gson



json abstract-class (4)

Deberá registrar JSONSerializer y JSONDeserializer. También puede implementar un adaptador genérico para todas sus interfaces de la siguiente manera:

  • Durante la serialización: agregue un META-info del tipo de clase impl real.
  • Durante la Deserialización: recupera esa meta información y llama al JSONDeserailize de esa clase

Aquí está la implementación que he usado para mí y funciona bien.

public class PropertyBasedInterfaceMarshal implements JsonSerializer<Object>, JsonDeserializer<Object> { private static final String CLASS_META_KEY = "CLASS_META_KEY"; @Override public Object deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { JsonObject jsonObj = jsonElement.getAsJsonObject(); String className = jsonObj.get(CLASS_META_KEY).getAsString(); try { Class<?> clz = Class.forName(className); return jsonDeserializationContext.deserialize(jsonElement, clz); } catch (ClassNotFoundException e) { throw new JsonParseException(e); } } @Override public JsonElement serialize(Object object, Type type, JsonSerializationContext jsonSerializationContext) { JsonElement jsonEle = jsonSerializationContext.serialize(object, object.getClass()); jsonEle.getAsJsonObject().addProperty(CLASS_META_KEY, object.getClass().getCanonicalName()); return jsonEle; } }

Entonces puede registrar este adaptador para todas sus interfaces de la siguiente manera

Gson gson = new GsonBuilder() .registerTypeAdapter(IInterfaceOne.class, new PropertyBasedInterfaceMarshal()) .registerTypeAdapter(IInterfaceTwo.class, new PropertyBasedInterfaceMarshal()).create();

Tengo un objeto de árbol en formato JSON que intento deserializar con Gson. Cada nodo contiene sus nodos secundarios como campos de tipo de objeto Nodo. Nodo es una interfaz, que tiene varias implementaciones de clase concretas. Durante el proceso de deserialización, ¿cómo puedo comunicarle a Gson qué clase concreta debo implementar al deserializar el nodo, si no sé a priori a qué tipo pertenece el nodo? Cada nodo tiene un campo de miembro que especifica el tipo. ¿Hay alguna manera de acceder al campo cuando el objeto está en forma serializada y de alguna manera comunicar el tipo a Gson?

¡Gracias!


Por lo que puedo decir, esto no funciona para los tipos que no son de colección, o más específicamente, las situaciones donde el tipo concreto se usa para serializar, y el tipo de interfaz se usa para deserializar. Es decir, si tiene una clase simple que implementa una interfaz y serializa la clase concreta, luego especifica la interfaz para deserializar, terminará en una situación irrecuperable.

En el ejemplo anterior, el adaptador de tipo se registra contra la interfaz, pero cuando se serializa utilizando la clase concreta, no se utilizará, lo que significa que nunca se establecerán los datos CLASS_META_KEY.

Si especifica el adaptador como un adaptador jerárquico (lo que le indica a gson que lo use para todos los tipos en la jerarquía), terminará en un bucle infinito ya que el serializador seguirá llamándose a sí mismo.

¿Alguien sabe cómo serializar desde una implementación concreta de una interfaz, luego deserializar usando solo la interfaz y un InstanceCreator?

Por defecto, parece que gson creará la instancia concreta, pero no configurará sus campos.

El problema se registra aquí:

http://code.google.com/p/google-gson/issues/detail?id=411&q=interface


Tienes que usar la clase TypeToken de Google Gson. Necesitarás, por supuesto, tiene una clase genérica T para que funcione

Type fooType = new TypeToken<Foo<Bar>>() {}.getType();

gson.toJson (foo, fooType);

gson.fromJson(json, fooType);


Sugeriría agregar un JsonDeserializer personalizado para Node s:

Gson gson = new GsonBuilder() .registerTypeAdapter(Node.class, new NodeDeserializer()) .create();

Podrá acceder al elemento JsonElement representa el nodo en el método del deserializador, convertirlo en un JsonObject y recuperar el campo que especifica el tipo. A continuación, puede crear una instancia del tipo correcto de Node basado en eso.