【问题标题】:Custom deserializer for RealmObjectRealmObject 的自定义反序列化器
【发布时间】:2016-11-10 19:06:31
【问题描述】:

出于学习目的,我正在使用 Realm 和 Edinburg Festival Api 创建一个 Android 应用程序。除了一个问题,一切都很顺利。

我正在使用以下方法将检索到的 JSON 转换为 RealmObjects:

public void onResponse(final String response) {
    realm.executeTransactionAsync(new Realm.Transaction(){
        @Override
        public void execute(Realm realm) {
            // Update our realm with the results
            parseImages();
            realm.createOrUpdateAllFromJson(Festival.class, response);
        }
    }
}

这工作正常,除了一个字段,图像。 JSON的图片部分:

"images": {    
    "031da8b4bad1360eddea87e8820615016878b183": {
        "hash": "031da8b4bad1360eddea87e8820615016878b183",
        "orientation": "landscape",
        "type": "hero",
        "versions": {
            "large-1024": {
            "height": 213,
            "mime": "image/png",
            "type": "large-1024",
        }
        "width": 1024
    }
}

这里的问题是图像对象内部的哈希。我不知道如何处理这个。每个节日的哈希值都不同。是否可以在我的 RealmObject 中制作自定义 JSON 反序列化器?

最后一个代码示例是我当前的模型:

public class Festival extends RealmObject {
    @PrimaryKey
    public String title;
    RealmList<Image> images;
    public String description_teaser;
    public String description;
    public String genre;
    public String age_category;
    public String website;
    public RealmList<Performance> performances;
    public int votes;
}

我知道我的 PK 不是最佳的,但这仍然只是为了让图像正常工作,我需要设置一个 PK 以进行迁移。

欢迎任何提示,干杯:)

更新

添加图片模型:

public class Image extends RealmObject {
    public String hash;
    public String orientation;
    public String type;
    RealmList<Version> versions;
}

更新 2

我尝试在调用 realm.createOrUpdateAllFromJson(Festival.class, response); 之前解析图像;

private void parseImages(String jsonString) throws JSONException {
    JSONArray jsonArr = new JSONArray(jsonString);
    for(int i = 0; i < jsonArr.length(); i++){
        JSONObject jsonObj = jsonArr.getJSONObject(i);
        JSONObject images = (JSONObject)jsonObj.get("images");
        Iterator<String> iter = images.keys();
        while (iter.hasNext()) {
            String key = iter.next();
            try {
                JSONObject value = json.get(key);
                realm.createOrUpdateObjectFromJson(Image.class,value);
            } catch (JSONException e) {
                // Something went wrong!
            }
        }
    }
}

更新 3

我创建了一个函数来清理我从 API 获得的损坏的 JSON。它不是很好,但它现在有效。它删除了哈希和奇怪的版本,并将它们都放在一个数组中。我确信它可以更有效地编写,但我会继续这样做,所以我现在可以继续我的应用程序的其余部分。请参阅我自己的答案。

【问题讨论】:

    标签: android json realm


    【解决方案1】:

    我自己的临时解决方案:

        /**
         * Function to fix the json coming from the Festival API
         * This is a bit more complicated then it needs to be but realm does not yet support @Serializedname
         * It removes the "large-1024" (and simllar) object and places the versions in a JSON version array
         * Then it removes the hashes and creates and images array. The JsonArray can now be parsed normally :)
         *
         * @param jsonString Result string from the festival api
         * @return JSONArray The fixed JSON in the form of a JSONArray
         * @throws JSONException
         */
        private JSONArray cleanUpJson(String jsonString) throws JSONException {
            JSONArray json = new JSONArray(jsonString);
            for(int i = 0; i < json.length(); i++){
                // We store the json Image Objects in here so we can remove the hashes
                Map<String,JSONObject> images = new HashMap<>();
                JSONObject festivalJson = json.getJSONObject(i);
                JSONObject imagesJson = (JSONObject)festivalJson.get("images");
                // Iterate each hash inside the images
                Iterator<String> hashIter = imagesJson.keys();
                while (hashIter.hasNext()) {
                    String key = hashIter.next();
                    try {
                        final JSONObject image = imagesJson.getJSONObject(key);
    
                        // Remove the version parents and map them to version
                        Map<String, JSONObject> versions = new HashMap<>();
                        JSONObject versionsJsonObject = image.getJSONObject("versions");
    
                        // Now iterate all the possible version and map add to the hashmap
                        Iterator<String> versionIter = versionsJsonObject.keys();
                        while(versionIter.hasNext()){
                            String currentVersion = versionIter.next();
                            versions.put(currentVersion,versionsJsonObject.getJSONObject(currentVersion));
                        }
    
                        // Use the hashmap to modify the json so we get an array of version
                        // This can't be done in the iterator because you will get concurrent error
                        image.remove("versions");
                        Iterator hashMapIter = versions.entrySet().iterator();
                        JSONArray versionJsonArray = new JSONArray();
                        while( hashMapIter.hasNext() ){
                            Map.Entry pair = (Map.Entry)hashMapIter.next();
                            versionJsonArray.put(pair.getValue());
                        }
                        image.put("versions",versionJsonArray);
                        Log.d(LOG_TAG,image.toString());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    images.put(key,imagesJson.getJSONObject(key));
                }
                // Now let's get rid of the hashes
                Iterator hashMapIter = images.entrySet().iterator();
                JSONArray imagesJsonArray = new JSONArray();
                while( hashMapIter.hasNext() ){
                    Map.Entry pair = (Map.Entry)hashMapIter.next();
                    imagesJsonArray.put(pair.getValue());
                }
                festivalJson.put("images", imagesJsonArray);
            }
            return json;
        }
    

    希望它对某人有所帮助:) 但肯定不整洁。

    【讨论】:

      【解决方案2】:

      由于这个 JSON 中的键是动态的(为什么这不是一个数组?设计这个 API 的人都不知道他们在做什么),you'll have to manually parse the object up to the point of the hash key

      JSONObject jsonObj = new JSONObject(jsonString);
      JSONObject images = (JSONObject)jsonObj.get("images");
      Iterator<String> iter = images.keys();
      while (iter.hasNext()) {
          String key = iter.next();
          try {
              JSONObject value = json.get(key);
              realm.createOrUpdateObjectFromJson(Image.class, value.toString());
          } catch (JSONException e) {
              // Something went wrong!
          }
      }
      

      【讨论】:

      • 感谢您的回答。我如何将它与我解析 json 的当前方式结合起来?我应该@ignore images 然后在添加图像后运行此代码吗?或者我可以在 realm.createOrUpdateAllFromJson 中以某种方式实现它吗?
      • 您需要先运行此代码,然后再将其提供给createOrUpdateAllFromJson
      • 每个图像对象都应该作为一个对象单独存储,同时逐个键解析图像。毕竟,哈希本身也可以在对象中找到,因此您不会丢失任何信息。 createOrUpdateAll 需要一个数组,但这不是一个数组。
      • 很抱歉再次打扰您,我无法正常工作。响应中的第一个对象是一系列节日。我试图遍历数组,然后使用您的代码。我已经上传了完整的 JSON 来澄清它:gist.github.com/RobAben/878c2577738e54ee61310586e95da335
      • 嗯,json 与呈现的内容略有不同-_-
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-21
      • 1970-01-01
      • 1970-01-01
      • 2016-02-13
      • 1970-01-01
      • 2018-02-19
      • 2011-04-12
      相关资源
      最近更新 更多