Ember model to json

后端 未结 12 1350
北恋
北恋 2020-12-13 13:55

I am looking for an efficient way to translate my Ember object to a json string, to use it in a websocket message below

/*
 * Model
 */

App.node = Ember.Obj         


        
相关标签:
12条回答
  • 2020-12-13 14:39

    Ember.js appears to have a JSON library available. I hopped into a console (Firebug) on one the Todos example and the following worked for me:

    hash = { test:4 }
    JSON.stringify(hash)
    

    So you should be able to just change your line to

    App.io.emit('node', { node:JSON.stringify(hash) })
    
    0 讨论(0)
  • 2020-12-13 14:42

    I have also been struggling with this. As Mirko says, if you pass the ember object to JSON.stringify you will get circular reference error. However if you store the object inside one property and use stringify on that object, it works, even nested subproperties.

    var node = Ember.Object.create({
      data: {
        name: 'theName',
        type: 'theType',
        value: 'theValue'
      }
    });
    
    console.log(JSON.stringify(node.get('data')));
    

    However, this only works in Chrome, Safari and Firefox. In IE8 I get a stack overflow so this isn't a viable solution.

    I have resorted to creating JSON schemas over my object models and written a recursive function to iterate over the objects using the properties in the schemas and then construct pure Javascript objects which I can then stringify and send to my server. I also use the schemas for validation so this solution works pretty well for me but if you have very large and dynamic data models this isn't possible. I'm also interested in simpler ways to accomplish this.

    0 讨论(0)
  • 2020-12-13 14:44

    I modified @Kevin-pauli solution to make it works with arrays as well:

    App.Jsonable = Ember.Mixin.create({
        getJson: function() {
            var v, json = {}, inspectArray = function (aSome) {
                if (Ember.typeof(aSome) === 'array') {
                    return aSome.map(inspectArray);
                }
                if (Jsonable.detect(aSome)) {
                    return aSome.getJson();
                } 
                return aSome;
            };
            for (var key in this) {
                if (this.hasOwnProperty(key)) {
                    v = this[key];
                    if (v === 'toString') {
                        continue;
                    } 
                    if (Ember.typeOf(v) === 'function') {
                        continue;
                    }
                    if (Ember.typeOf(v) === 'array') {
                        v = v.map(inspectArray);
                    }
                    if (App.Jsonable.detect(v))
                        v = v.getJson();
                    json[key] = v;
                }
            }
            return json;
        }
    });
    

    I also made some further modification to get the best of both worlds. With the following version I check if the Jsonable object has a specific property that informs me on which of its properties should be serialized:

    App.Jsonable = Ember.Mixin.create({
        getJson: function() {
            var v, json = {}, base, inspectArray = function (aSome) {
                if (Ember.typeof(aSome) === 'array') {
                    return aSome.map(inspectArray);
                }
                if (Jsonable.detect(aSome)) {
                    return aSome.getJson();
                } 
                return aSome;
            };
            if (!Ember.isNone(this.get('jsonProperties'))) {
                // the object has a selective list of properties to inspect
                base = this.getProperties(this.get('jsonProperties'));
            } else {
                // no list given: let's use all the properties
                base = this;
            }
            for (var key in base) {
                if (base.hasOwnProperty(key)) {
                    v = base[key];
                    if (v === 'toString') {
                        continue;
                    } 
                    if (Ember.typeOf(v) === 'function') {
                        continue;
                    }
                    if (Ember.typeOf(v) === 'array') {
                        v = v.map(inspectArray);
                    }
                    if (App.Jsonable.detect(v))
                        v = v.getJson();
                    json[key] = v;
                }
            }
            return json;
        }
    });
    

    I am using this little tweak and I am happy with it. I hope it'll help others as well!

    Thanks to @pangratz and @Kevin-Pauli for their solution!

    0 讨论(0)
  • 2020-12-13 14:48

    Ember Data Model's object counts with a toJSON method which optionally receives an plain object with includeId property used to convert an Ember Data Model into a JSON with the properties of the model.

    https://api.emberjs.com/ember-data/2.10/classes/DS.Model/methods/toJSON?anchor=toJSON

    You can use it as follows:

    const objects = models.map((model) => model.toJSON({ includeId: true }));
    

    Hope it helps. Enjoy!

    0 讨论(0)
  • 2020-12-13 14:48

    Will this work for you?

    var json = JSON.stringify( Ember.getMeta( App.node, 'values') );
    

    The false is optional, but would be more performant if you do not intend to modify any of the properties, which is the case according to your question. This works for me, but I am wary that Ember.meta is a private method and may work differently or not even be available in future releases. (Although, it isn't immediately clear to me if Ember.getMeta() is private). You can view it in its latest source form here:

    https://github.com/emberjs/ember.js/blob/master/packages/ember-metal/lib/utils.js

    The values property contains only 'normal' properties. You can collect any cached, computed properties from Ember.meta( App.node, false ).cached. So, provided you use jQuery with your build, you can easily merge these two objects like so:

    $.extend( {}, Ember.getMeta(App.node, 'values'), Ember.getMeta(App.node, 'cache') );
    

    Sadly, I haven't found a way to get sub-structures like array properties in this manner.

    0 讨论(0)
  • 2020-12-13 14:50

    You can get a plain JS object (or hash) from an Ember.Object instance by calling getProperties() with a list of keys.

    If you want it as a string, you can use JSON.stringify().

    For example:

    var obj  = Ember.Object.create({firstName: 'Erik', lastName: 'Bryn', login: 'ebryn'}),
        hash = obj.getProperties('firstName', 'lastName'), // => {firstName: 'Erik', lastName: 'Bryn'}
        stringHash = JSON.stringify(hash); // => '{"firstName": "Erik", "lastName": "Bryn"}'
    
    0 讨论(0)
提交回复
热议问题