如何对Ember对象进行序列化?

6
我需要使用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对象的最佳方法吗?是否有推荐的技术?
3个回答

8

对于序列化和反序列化,您可以按照以下方式处理,参见 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()的输出中? - hekevintran
我不是JavaScript专家,所以这里只能猜测:如果你在一个Ember.Object上执行for (prop in obj) {},那么没有列出任何__ember*,并且对于已定义的属性,obj.hasOwnProperty的检查只返回true,参见http://jsfiddle.net/pangratz666/w53DH/。 - pangratz
__ember* 属性不会在 for...in 循环中列出。执行 App.obj.hasOwnProperty('__ember1335029966963') 返回 true - hekevintran

0

我有:

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

    //由Shimon Doodkin修改
    //基于@leo,@pangratz,@kevin-pauli,@Klaus的答案
    //https://dev59.com/E2oy5IYBdhLWcg3wQr5i
    
    App.Jsonable = Em.Mixin.create({
        getJson : function (keysToSkip, visited) {
            //没有参数调用getJson(),
            //它们在递归期间传递值。
    
            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];
    
                // 通常存在循环引用
                // 在键:ownerView、controller、context === base上
    
                if ( value === base ||
                     value === 'toString' ||
                     Em.typeOf(value) === 'function')
                    continue;
    
                // 可选的,也可以不用这个,
                // 上面的规则如果value === base覆盖了通常情况
                if (visited.indexOf(value) != -1)
                    continue;
    
                json[key] = jsonValue(value, key, base);
    
            }
    
            visited.pop();
            return json;
        }
    });
    
    /*
    例子:
    
    DeliveryInfoInput = Ember.Object.extend(App.Jsonable,{
     jsonProperties: ["title","value","name"], //可选指定json属性
     title:"",
     value:"",
     input:false,
     textarea:false,
     size:22,
     rows:"",
     name:"",
     hint:""
    })
    */
    

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

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