2014-10-09 87 views
18

我的目標是將用GSON實例化的對象保存到數據庫合併Realm對象和Gson對象

我的問題是這樣的:

  • 我可以實例與GSON一個對象,所以GSON通吃的特性, 的護理,但那麼它不會被持久化到數據庫

  • 我可以使用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); 

這是行不通的,因爲你必須使用

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可能有效。

關於如何解決這個難題的任何想法?

回答

13

Emanuele from Realm here。

現在的解決方案是不理想的,並在其中一個例子,提出:https://github.com/realm/realm-java/blob/master/examples/gridViewExample/src/main/java/io/realm/examples/realmgridview/GridViewExampleActivity.java

我們正在努力使經驗的方式更流暢!

+1

我正在研究這個例子:)你到目前爲止做的很好!如果我理解正確,在這個例子中你手動設置了setters。 與此同時,我正在尋找一個堅實的deepcopy-all-the-properties解決方案的互聯網:) – TomCB 2014-10-09 10:05:36

+0

請讓我們更新關於這個問題。如果您找不到解決方案,請告訴社區!我們一起可以解決問題! – TomCB 2014-10-13 10:58:10

+2

我對如何解決這個問題有一個堅實的想法。我會盡力開發一個概念證明。 – Emanuelez 2014-10-13 12:18:14

2

正如之前在Gson實例中註冊序列號爲RealmObject的答案中所述,適當的JsonSerializer應該被註冊。在我的例子中,Gson的通用JsonSerializer與getters而不是字段一起使用。

首先,它應該與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來源(甚至由境界創建)類得到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); 
      } 
     } 
    } 
} 
+0

什麼是checkstate? – Olayinka 2016-01-20 21:36:44

+0

對不起,你的意思是?你能解釋你的問題嗎? – 2016-01-22 15:54:43

+0

這很好用。另一件需要記住的事情是,只有在創建RealmObject的同一個線程中調用它纔會起作用,否則它將拋出Realm異常。如果你的模型類不使用這個註解,也可以刪除if(f.isAnnotationPresent(Expose.class))。 – velval 2016-09-08 07:41:24

0

這可以用一行代碼來實現。

在管理RealmObject內存獲取副本,並把它傳遞給GSON

String jsonVacature = new Gson().toJson(realm.copyFromRealm(vacature)); 

檢查this answer的詳細信息和其他的解決方案。