【问题标题】:How do you serialise Ember objects?你如何序列化 Ember 对象?
【发布时间】:2012-04-21 07:30:10
【问题描述】:

我需要使用 localStorage 来存储一些 Ember 对象。我注意到 Ember 对象的属性名称类似于 __ember1334992182483。当我在 Ember 对象上调用 JSON.stringify() 时,这些 __ember* 属性不会序列化。为什么是这样?我并不是说我想序列化这些属性。我只是好奇它们到底是什么以及它们是如何实现的,因此它们不会被序列化。

我正在使用 cycle.js (https://github.com/douglascrockford/JSON-js/blob/master/cycle.js) 将包含重复引用的数据结构编码为可用于重建原始数据结构的字符串。它可以让你这样做:

a = {a:1}
b = {b:1}
c = [[a, b], [b, a]]

foo = JSON.stringify(JSON.decycle(c))  // "[[{'a':1},{'b':1}],[{'$ref':'$[0][1]'},{'$ref':'$[0][0]'}]]"
JSON.retrocycle(JSON.parse(foo))  // reconstruct c

对于 Ember 对象,我可以做同样的事情,但我还需要将反序列化的对象传递给 Ember.Object.create(),因为它们被反序列化为纯 JavaScript 对象。

这是序列化/反序列化 Ember 对象的最佳方式吗?对此有推荐的技术吗?

【问题讨论】:

    标签: serialization deserialization ember.js


    【解决方案1】:

    对于序列化和反序列化,您可以执行以下操作,请参阅http://jsfiddle.net/pangratz666/NVpng/

    App.Serializable = Ember.Mixin.create({
        serialize: function() {
            var propertyNames = this.get('propertyNames') || [];
            return this.getProperties(propertyNames);
        },
    
        deserialize: function(hash) {
            this.setProperties(hash);
        }
    });
    
    App.Person = Ember.Object.extend(App.Serializable, {
        propertyNames: 'firstName title fullName'.w(),
        fullName: function() {
            return '%@ %@'.fmt(this.get('title'), this.get('firstName'));
        }.property('firstName', 'title')
    });
    
    var hansi = App.Person.create({
        firstName: 'Hansi',
        title: 'Mr.'
    });
    
    // { firstName: 'hansi', title: 'Mr.', fullName: 'Mr. Hansi' }
    console.log( hansi.serialize() );
    
    var hubert = App.Person.create();
    hubert.deserialize({
        firstName: 'Hubert',
        title: 'Mr.'
    });
    console.log( hubert.serialize() );​
    

    更新:也可以看看类似的问题Ember model to json

    【讨论】:

    • 为什么__ember* 的属性不在JSON.stringify() 的输出中?
    • 我不得不在这里猜测,因为我不是 JavaScript 专家:但如果你在 Ember.Object 上执行 for (prop in obj) {},则不会列出 __ember*,并且仅检查 obj.hasOwnProperty为已定义的属性返回 true,请参阅 jsfiddle.net/pangratz666/w53DH
    • __ember* 属性未在for...in 循环中列出。执行App.obj.hasOwnProperty('__ember1335029966963') 返回true
    【解决方案2】:

    我会使用 ember-data 并为此编写一个数据存储适配器。

    【讨论】:

      【解决方案3】:

      我有:

      • 固定和简化的代码
      • 添加了循环引用预防
      • 增加了 get of value 的使用
      • 删除了空组件的所有默认属性

        //Modified by Shimon Doodkin 
        //Based on answers of: @leo, @pangratz, @kevin-pauli, @Klaus
        //http://stackoverflow.com/questions/8669340
        
        App.Jsonable = Em.Mixin.create({
            getJson : function (keysToSkip, visited) {
                //getJson() called with no arguments,
                // they are to pass on values during recursion.
        
                if (!keysToSkip)
                    keysToSkip = Object.keys(Ember.Component.create());
        
                if (!visited)
                    visited = [];
        
                visited.push(this);
        
                var getIsFunction;
        
                var jsonValue = function (attr, key, obj) {
                    if (Em.isArray(attr))
                        return attr.map(jsonValue);
                    if (App.Jsonable.detect(attr))
                        return attr.getJson(keysToSkip, visited);
                    return getIsFunction?obj.get(key):attr;
                };
        
                var base;
                if (!Em.isNone(this.get('jsonProperties')))
                    base = this.getProperties(this.get('jsonProperties'));
                else
                    base = this;
        
                getIsFunction=Em.typeOf(base.get) === 'function';
        
                var json = {};
        
                var hasProp = Object.prototype.hasOwnProperty;
        
                for (var key in base) {
        
                    if (!hasProp.call(base, key) || keysToSkip.indexOf(key) != -1)
                        continue;
        
                    var value = base[key];
        
                    // there are usual circular references
                    // on keys: ownerView, controller, context === base
        
                    if ( value === base ||
                         value === 'toString' ||
                         Em.typeOf(value) === 'function')
                        continue;
        
                    // optional, works also without this,
                    // the rule above if value === base covers the usual case
                    if (visited.indexOf(value) != -1)
                        continue;
        
                    json[key] = jsonValue(value, key, base);
        
                }
        
                visited.pop();
                return json;
            }
        });
        
        /*
        example:
        
        DeliveryInfoInput = Ember.Object.extend(App.Jsonable,{
         jsonProperties: ["title","value","name"], //Optionally specify properties for json
         title:"",
         value:"",
         input:false,
         textarea:false,
         size:22,
         rows:"",
         name:"",
         hint:""
        })
        */
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 2015-06-28
        • 2011-04-06
        • 1970-01-01
        相关资源
        最近更新 更多