Слияние объекта Realm и объекта Gson
Моя цель - сохранить объект, созданный с помощью GSON, в базу данных с помощью области.
Моя проблема заключается в следующем:
-
Я могу создать объект с помощью GSON, поэтому GSON позаботится обо всех свойствах,
но тогда он не будет сохранен для db
-
Я могу создать экземпляр объекта с помощью Realm, но затем я должен заполнить все настройки для свойств.
В моем oncreate эта часть одинакова для обоих методов
//delete previous realm file
Realm.deleteRealmFile(this);
//gson instance
Gson gson = new Gson();
//realm instance
realm = Realm.getInstance(this);
** Название моего класса - Vacature **
Информация: Я знаю, что следующий код должен быть внутри:
realm.beginTransaction();
// code here
realm.commitTransaction();
Вариант 1:
//get class with gson
Vacature vacatureGson = gson.fromJson(jsonString, Vacature.class);
Это не сработает, потому что вы должны создать экземпляр объекта realm, используя
Class instance = realm.createObject(Class.class); // Create a new object
Вариант 2:
//get instance with gson
Vacature vacatureGson = gson.fromJson(jsonString, Vacature.class);
//make instance with realm
Vacature realmVacature = realm.createObject(Vacature.class);
realmVacature = vacatureGson;
Это не сработает, потому что это не является правильным способом скопировать все свойства с одного объекта на другой.
Если есть хороший способ скопировать все свойства из gsonObject в объект realmObject,
вариант 2 может работать.
Любые идеи о том, как решить эту загадку?
Ответы
Ответ 1
Эмануэле из Царства здесь.
В настоящее время решение является субоптимальным и представлено в одном из примеров: https://github.com/realm/realm-java/blob/master/examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/GridViewExampleActivity.java
Мы работаем над тем, чтобы сделать процесс более плавным!
Ответ 2
Как было сказано в предыдущих ответах для сериализации RealmObject
с Gson, соответствующий экземпляр JsonSerializer
должен быть зарегистрирован в экземпляре Gson. Ниже моего примера универсального JsonSerializer
для Gson, который работает с геттерами вместо полей.
Во-первых, он должен быть зарегистрирован в Gson, чтобы использовать вот так:
@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();
}
И тогда можно получить JSON из любого производного класса RealmObject (и даже созданного с помощью Realm) следующим образом:
public class MessageModel extends RealmObject { ... }
String json = createGson().toJson(messageModelInstance);
И вы можете скопировать MessageModel
следующим образом:
MessageModel src= ...;
MessageModel dst= ...;
Serializer.newInstance(MessageModel.class).copy(src, dst);
И здесь 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);
}
}
}
}
Ответ 3
Это может быть достигнуто с помощью ОДНОЙ ЛИНИИ КОДА.
Получить копию в памяти управляемого объекта RealmObject и передать ее в Gson
String jsonVacature = new Gson().toJson(realm.copyFromRealm(vacature));
Проверьте этот ответ для получения более подробной информации и других решений.