Подтвердить что ты не робот

Слияние объекта 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 может работать.

Любые идеи о том, как решить эту загадку?

4b9b3361

Ответ 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));

Проверьте этот ответ для получения более подробной информации и других решений.