java - deserializar - Fusión de objeto de reino y objeto de Gson
deserializar json java (3)
Como se dijo en las respuestas anteriores para serializar RealmObject
con Gson, el JsonSerializer
apropiado debe registrarse en la instancia de Gson. A continuación, mi ejemplo de un JsonSerializer
universal para Gson que funciona con captadores en lugar de campos.
En primer lugar, debe estar registrado con Gson para poder utilizarlo así:
@NonNull private static Gson createGson() {
GsonBuilder gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
try {
gsonBuilder.registerTypeAdapter(Class.forName("io.realm.<YourClassName1>RealmProxy"), Serializer.newInstance(<YourClassName1>.class));
gsonBuilder.registerTypeAdapter(Class.forName("io.realm.<YourClassName2>RealmProxy"), Serializer.newInstance(<YourClassName2>.class));
...
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return gsonBuilder.create();
}
Y luego es posible obtener JSON de cualquier clase derivada de RealmObject (e incluso creada por Realm) como esta:
public class MessageModel extends RealmObject { ... }
String json = createGson().toJson(messageModelInstance);
Y puedes copiar MessageModel
así:
MessageModel src= ...;
MessageModel dst= ...;
Serializer.newInstance(MessageModel.class).copy(src, dst);
Y aquí el Serializer
public class Serializer<T> implements JsonSerializer<T> {
private Class<T> clazz;
private Serializer(Class<T> clazz) {this.clazz = clazz;}
@NonNull
public static <T> Serializer<T> newInstance(Class<T> clazz) {return new Serializer<T>(clazz);}
@Override
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
if (f.isAnnotationPresent(Expose.class)) try {
String name = f.getName();
String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
Method method = src.getClass().getMethod(methodName);
Object o = method.invoke(src);
if (o instanceof String) {
jsonObject.addProperty(name, (String) o);
}
else if (o instanceof Number) {
jsonObject.addProperty(name, (Number) o);
}
else if (o instanceof Boolean) {
jsonObject.addProperty(name, (Boolean) o);
}
else if (o instanceof Character) {
jsonObject.addProperty(name, (Character) o);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return jsonObject;
}
public <T> void copy(T src, T dst) {
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
if (f.isAnnotationPresent(Expose.class)) try {
String name = f.getName();
String getterName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
String setterName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
Method getter = clazz.getMethod(getterName);
Method setter = clazz.getMethod(setterName, f.getType());
setter.invoke(dst, getter.invoke(src));
} catch (Exception e) {
e.printStackTrace();
checkState(false);
}
}
}
}
Mi objetivo es persistir un objeto instanciado con GSON en la base de datos con el dominio .
Mi problema es el siguiente:
Puedo crear una instancia de un objeto con GSON, por lo que GSON se encarga de todas las propiedades, pero luego no se mantendrá en db
Puedo crear una instancia de un objeto con Realm, pero luego tengo que completar todos los configuradores de las propiedades.
En mi oncreate, esta parte es la misma para ambos métodos.
//delete previous realm file
Realm.deleteRealmFile(this);
//gson instance
Gson gson = new Gson();
//realm instance
realm = Realm.getInstance(this);
** El nombre de mi clase es Vacature **
Información: Soy consciente de que el siguiente código debe estar dentro:
realm.beginTransaction();
// code here
realm.commitTransaction();
Opción 1:
//get class with gson
Vacature vacatureGson = gson.fromJson(jsonString, Vacature.class);
Esto no funcionará porque tienes que instanciar un objeto de reino usando
Class instance = realm.createObject(Class.class); // Create a new object
Opcion 2:
//get instance with gson
Vacature vacatureGson = gson.fromJson(jsonString, Vacature.class);
//make instance with realm
Vacature realmVacature = realm.createObject(Vacature.class);
realmVacature = vacatureGson;
Esto no funcionará porque no es una forma adecuada de copiar todas las propiedades de un objeto a otro. Sin embargo, si existe una buena manera de copiar todas las propiedades del objeto gsonObject al objeto realmObject, la opción 2 podría funcionar.
¿Alguna idea sobre cómo resolver este rompecabezas?
Emanuele del reino aquí.
En este momento, la solución es subóptima y se presenta en uno de los ejemplos: https://github.com/realm/realm-java/blob/master/examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/GridViewExampleActivity.java
¡Estamos trabajando para hacer que la experiencia sea más suave!
Esto se puede lograr con UNA LINEA DE CÓDIGO .
Obtenga una copia en la memoria del RealmObject administrado y páselo a Gson
String jsonVacature = new Gson().toJson(realm.copyFromRealm(vacature));
Compruebe esta respuesta para más detalles y para otras soluciones.