如何在Java Realm中将RealmObject序列化为JSON?

9
我正在为我的应用程序实现一个数据库,并尝试将其与我的REST接口“连接”起来。数据以JSON格式传输,使用新的JSON-Support(自Realm 0.76起)后,我可以将JSON传递给Realm.createObjectFromJson(MyType.class, jsonString),它会创建适当的对象和RealmLists。
但是,我该如何做相反的操作?即,将一个RealmObject序列化为JSON?它还应该序列化对象内的任何RealmList。
6个回答

12

简单来说,你需要做的就是:

Gson gson = //... obtain your Gson
YourRealmObject realmObj = realm.where(YourRealmObject.class).findFirst();
if(realmObj != null) {
    realmObj = realm.copyFromRealm(realmObj); //detach from Realm, copy values to fields
    String json = gson.toJson(realmObj);
}

这个代码是'realmObj = realmObj.copyFromRealm();'还是'obj = realm.copyFromRealm(realmObj);'?第二个对我起作用了。 - Sakkeer Hussain
1
@SakkeerHussain 抱歉,我一直认为RealmObject知道如何分离自己,但实际上是realm.copyFromRealm(realmObject)。我已经相应地编辑了帖子。 - EpicPandaForce
@EpicPandaForce 这样做可能非常低效。建议创建自己的gson TypeAdapter。 - The-null-Pointer-
但对于一个很重的对象,它会导致用户界面冻结。 - Gk Mohammad Emon
@GkMohammadEmon 那就不要在 UI 线程上执行? - EpicPandaForce
显示剩余2条评论

7

要将JSON反序列化为RealmObject,请使用以下之一:

假设您有以下类定义:

 @RealmClass
 public class Foo extends RealmObject{
  private String name;
  public void setName(String name){ this.name = name}
  public String getName(){ return this.name}
} 

并且一个类似于这样的json有效载荷:

 String json = "{\"name\":\"bar\"}";
 Foo fooObject= realm.createObjectFromJson(Foo.class, json);
 //or 
 String jsonArray = "[{\"name\":\"bar\"},{\"name\":\"baz\"}]";
 RealmList<Foo> fooObjects = realm.createAllFromJson(Foo.class, jsonArray);

然而,realm-core并不直接支持反向操作。所以我是这样解决的。我试图使用GSON,但最终写了太多我自己都不理解的代码,所以我实现了自己的适配器。问题在于RealmObjects不是'realm' java.lang.Object

创建一个适配器,它接受您的realm对象实例并返回其JSON表示形式。

例如.

 public class RealmJsonAdapter{
    public JSONObject toJson(Foo foo){
     JSONObject obj = new JSONObject();
     obj.putString("name",foo.getName());
     //if you have more fields you continue
     return obj;
     }
   }

现在您可以在类中使用此适配器将您的RealmObject序列化为JSON。最好将适配器设置为接口,以便让调用者(可能是您自己)传递他们想要使用的适配器。然后,您可以调用例如adapter.toJSON(realmObjectInstance),并获得您的JSONObject实现,因为您只关心JSON而不是RealmObject。
注意:这个解决方案有点过时了。RealmObjects现在是真正的Java对象,所以您应该能够毫无问题地与GSON一起使用它。只需确保您使用的是0.89或更高版本,一切都会正常工作。

6

来自Realm的Christian。 目前,Android版Realm没有这样的方法,尽管核心数据库实际上支持JSON序列化,所以现在您要么手动完成,要么使用第三方工具(例如GSON),但需要注意的是,我还没有测试过这种情况。


谢谢您的回复。您能给我一些提示如何手动完成吗?我尝试通过覆盖toString方法来实现这个目标,但似乎我只能在我的RealmObject类中拥有字段的setter/getter,除此之外没有其他方法。 - degill
我可能会在侧面创建一个Util类,该类接受您的模型类并输出JSON。您可以以多种方式构造JSON。手动或使用JSONObject / JSONArray。 - Christian Melchior
@ChristianMelchior 请问手动完成这个过程需要哪些步骤?您是否需要将RealmObject转换回原始对象? - Alan
@ChristianMelchior - 我们何时能够看到这个功能的发布? - ChaturaM
我们目前并没有积极地开发原生的JSON支持,但是我们即将合并这个PR https://github.com/realm/realm-java/pull/1849。如果你将它与GSON结合使用,就可以在不使用自定义GSON序列化器的情况下将其转换回JSON。 - Christian Melchior

1
以下是使用GSON库完成此操作的步骤。
假设我们从服务器收到了以下JSON响应:
{
   "data": [
      {
         "id": "1",
         "name": "John",
         "surname": "Doe"
      }
   ]
}

对于这个Json对象,我们创建一个带有相应属性的辅助类。
    public class JsonHelperClass {

    String id;
    String name;
    String surname;

    public JsonHelperClass() {
    }

    public JsonHelperClass(String id, String name, String surname) {
        this.id = id;
        this.name = name;
        this.surname = surname;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSurname() {
        return surname;
    }
    public void setSurname(String surname) {
        this.surname = surname;
    }
}

现在,以下是jsonReply,其中包含来自服务器的回复字符串。
    JSONArray jsonArray = new HttpManager().getJsonArrayFromReply(jsonReply);

    if(jsonArray == null || jsonArray.length <0){
        return;
    }

    for (int i = 0; i < jsonArray.length(); i++) {

        JSONObject json = null;
        try {
        json = (JSONObject) array.get(i);
        } catch (JSONException e) {
        return null;
        }

        Gson gson = new Gson();

        JsonHelperClass helperClass = gson.fromJson(json.toString(), JsonHelperClass.class);

        createRealmObject(helperClass);

}


    public void createRealmObject(JsonHelperClass helperClass){

        Realm realm = Realm.getInstance(context);

        realm.beginTransaction();

        RealmDataObject obj = realm.createObject(RealmDataObject.class);

        obj.setId(helperClass.getId());
        obj.setName(helperClass.getName());
        obj.setSurname(helperClass.getSurname());

        realm.commitTransaction();


}

     public JSONArray getJsonArrayFromReply(String reply){

        JSONArray array = null;

        try {
            JSONObject jsonResp = new JSONObject(reply);
            array = jsonResp.getJSONArray("data");

        } catch (JSONException e) {
            return null;
        }

        return array;
    }

和Realm数据对象

    public class RealmDataObject extends RealmObject {

    private String id;
    private String name;
    private String surname;

    public RealmDataObject() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }


}

这个基本上是序列化过程的一部分,从0.76版本开始由Realm处理。我想做相反的事情,即将一个对象放入其字符串表示中。目前,我只编写了自己的反序列化器,并且我对此感到满意。至于你的答案:从Realm的0.77版本开始,您可以省略HelperClass,因为您不再需要仅通过Realm创建对象。您可以简单地使用new RealmDataObject()并填充数据,甚至更简单,让Gson完成工作(就像在HelperClass中所做的那样)。 - degill
我必须研究一下这个问题...并且RealmDataObject是线程安全的吗? - J.Vassallo
嗨,我非常想了解更多关于RealmDataObject的内容,但是找不到任何相关文章,你知道有什么资料吗?谢谢。 - J.Vassallo
好的,我弄混了,抱歉...在这种情况下使用帮助程序是因为添加操作是从不同的线程执行的...而且安卓中的 Realm 对象不是线程安全的。 - J.Vassallo
1
但是,更简单的方法是不需要使用Gson转换您的JSONArray,您可以直接调用:JSONArray jsonArray = new HttpManager().getJsonArrayFromReply(jsonReply); realm.createAllFromJson(RealmDataObject.class, jsonArray);现在,更简单的方法是将您的jsonReply直接传递给您的realmrealm.createAllFromJson(RealmDataObject.class, jsonReply); 您不需要转换任何内容。只需将从网络获取的字符串传递给您的realm... - degill
显示剩余2条评论

0
对于我的情况:new Gson().toJson(realm.copy(realmObj)); 导致UI冻结 (有时会出现内存不足异常)。因此我更新了我的Gson实例,如下所示:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

String jsonString = gson.toJson(realm.copy(realmObj));

0

试一下

  private JSONArray convertRealmintoJSONArray(Activity context){
    try {
        RealmResults<ModelMyCart> results = RealmControllerMyCart.with(context).getBooks();
        JSONArray jsonArray = new JSONArray();
        for (ModelMyCart myCart : results
                ) {
            JSONObject object = new JSONObject();
            object.put(Constants.PRODUCT_ID, myCart.getId());
            object.put(Constants.PRODUCT_TITLE, myCart.getProduct_title());
            object.put(Constants.PRODUCT_SIZE, myCart.getProduct_size());
            object.put(Constants.PRODUCT_SELLINGFEE, myCart.getProduct_sellingfee());
            object.put(Constants.PRODUCT_SELLINGFEE, myCart.getShipping_price());
            object.put(Constants.PRODUCT_IMAGE, myCart.getProduct_image());
            object.put(Constants.PRODUCT_BRAND, myCart.getProduct_brand());
            object.put(Constants.PRODUCT_CATEGORY_ID, myCart.getProduct_category_id());
            object.put(Constants.PRODUCT_CATEGORY_NAME, myCart.getProduct_category_name());
            object.put(Constants.PRODUCT_COLOR, myCart.getProduct_color());
            object.put(Constants.PRODUCT_COLORTYPE, myCart.getProduct_colortype());
            object.put(Constants.PRODUCT_CONDITION, myCart.getProduct_condition());
            object.put(Constants.PRODUCT_CREATED_DATE, myCart.getProduct_created_date());
            object.put(Constants.PRODUCT_MYSALEPRICE, myCart.getProduct_mysaleprice());
            object.put(Constants.PRODUCT_ORIGINALPRICE, myCart.getProduct_originalprice());
            object.put(Constants.PRODUCT_POTENTIALEARNINGS, myCart.getProduct_potentialearnings());
            object.put(Constants.PRODUCT_SHIPPINGCHARGES, myCart.getProduct_shippingcharges());
            object.put(Constants.USER_ID, myCart.getUser_id());
            object.put(Constants.USER_UNAME, myCart.getUser_uname());
            jsonArray.put(object);
        }
        Log.e("Converted",""+jsonArray);
        return jsonArray;
    }catch (Exception e){

    }
    return null;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接