合并 Realm 对象和 Gson 对象

2022-09-02 13:47:28

我的目标是将一个使用 GSON 实例化的对象持久化到具有 Realm 的数据库中

我的问题是以下几点:

  • 我可以使用GSON实例化对象,因此GSON会处理所有属性,但随后它不会持久化到db中

  • 我可以使用 Realm 实例化一个对象,但是我必须填写属性的所有 setter。

在我的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);

这不起作用,因为您必须使用

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

来自 Realm 的 Emanuele 在这里。

目前,解决方案尚不理想,并在其中一个例子中提出:https://github.com/realm/realm-java/blob/master/examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/GridViewExampleActivity.java

我们正在努力使体验更加顺畅!


答案 2

正如在之前使用Gson序列化的答案中所说的那样,应该在Gson实例中注册适当的答案。下面我举了一个通用的Gson示例,它适用于getter而不是字段。RealmObjectJsonSerializerJsonSerializer

首先,它应该在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();
    }

然后可以从任何 RealmObject 派生的(甚至由 Realm 创建的)类中获取 JSON,如下所示:

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);
            }
        }
    }
}

推荐