Я ищу эффективный способ преобразовать мой объект Ember в строку json, чтобы использовать ее в сообщении websocket ниже
/*
* Model
*/
App.node = Ember.Object.extend({
name: 'theName',
type: 'theType',
value: 'theValue',
})
Метод websocket:
App.io.emit('node', {node: hash});
hash должен быть json-представлением узла. {name: thename, type: theType, ..} Должен быть быстрый onliner, чтобы сделать это... Я не хочу делать это вручную, так как у меня много атрибутов и они могут меняться...
У меня есть:
удалены все свойства по умолчанию для пустого компонента
//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:""
})
*/
Я написал обширную статью о том, как вы можете конвертировать модели ember в собственные объекты или JSON, которые могут помочь вам или другим:)
http://pixelchild.com. au / post / 44614363941 / как конвертировать угольные объекты в json s>
Я также боролся с этим. Как говорит Мирко, если вы передадите объект ember в JSON.stringify, вы получите ошибку циклической ссылки. Однако, если вы храните объект в одном свойстве и используете для него stringify, он работает, даже если вложенные свойства принадлежат.
var node = Ember.Object.create({
data: {
name: 'theName',
type: 'theType',
value: 'theValue'
}
});
console.log(JSON.stringify(node.get('data')));
Однако, это работает только в Chrome, Safari и Firefox. В IE8 я получаю переполнение стека, так что это не жизнеспособное решение.
Я прибег к созданию JSON-схем для своих объектных моделей и написал рекурсивную функцию для итерации по объектам с использованием свойств в схемах, а затем для создания чистых объектов Javascript, которые затем я могу преобразовать в строку и отправить на свой сервер. Я также использую схемы для проверки, так что это решение работает довольно хорошо для меня, но если у вас очень большие и динамические модели данных, это невозможно. Мне также интересны более простые способы сделать это.
Я изменил решение @ Kevin-pauli, чтобы оно работало также и с массивами:
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;
}
});
Я также внес некоторые дополнительные изменения, чтобы получить лучшее из обоих миров. В следующей версии я проверяю, обладает ли объект Jsonable определенным свойством, которое информирует меня о том, какие из его свойств следует сериализовать:
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;
}
});
Я использую этот небольшой твик и доволен им. Я надеюсь, что это поможет и другим!
Спасибо @pangratz и @ Kevin-Pauli за их решение!