Javascript Ember 模型到 json
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8669340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ember model to json
提问by Stephan
I am looking for an efficient way to translate my Ember object to a json string, to use it in a websocket message below
我正在寻找一种有效的方法将我的 Ember 对象转换为 json 字符串,以在下面的 websocket 消息中使用它
/*
* Model
*/
App.node = Ember.Object.extend({
name: 'theName',
type: 'theType',
value: 'theValue',
})
The websocket method:
网络套接字方法:
App.io.emit('node', {node: hash});
hash should be the json representation of the node. {name: thename, type: theType, ..} There must be a fast onliner to do this.. I dont want to do it manualy since i have many attributes and they are likely to change..
hash 应该是节点的 json 表示。{name: thename, type: theType, ..} 必须有一个快速的在线工具才能做到这一点.. 我不想手动进行,因为我有很多属性而且它们很可能会改变..
采纳答案by Esteban Borai
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.
Ember DataModel
的对象使用一种toJSON
方法进行计数,该方法可选择接收带有includeId
属性的普通对象,用于将 Ember 数据模型转换为具有模型属性的 JSON。
https://api.emberjs.com/ember-data/2.10/classes/DS.Model/methods/toJSON?anchor=toJSON
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!
希望能帮助到你。享受!
回答by pangratz
As stated you can take inspiration from the ember-runtime/lib/core.js#inspectfunction to get the keys of an object, see http://jsfiddle.net/pangratz666/UUusD/
如前所述,您可以从ember-runtime/lib/core.js#inspect函数中获取灵感来获取对象的键,请参阅http://jsfiddle.net/pangratz666/UUusD/
App.Jsonable = Ember.Mixin.create({
getJson: function() {
var v, ret = [];
for (var key in this) {
if (this.hasOwnProperty(key)) {
v = this[key];
if (v === 'toString') {
continue;
} // ignore useless items
if (Ember.typeOf(v) === 'function') {
continue;
}
ret.push(key);
}
}
return this.getProperties.apply(this, ret);
}
});
Note, since commit 1124005- which is available in ember-latest.js
and in the next release - you can pass the ret
array directly to getProperties
, so the return statement of the getJson
function looks like this:
请注意,由于提交1124005-ember-latest.js
在下一个版本中可用- 您可以将ret
数组直接传递给getProperties
,因此getJson
函数的 return 语句如下所示:
return this.getProperties(ret);
回答by ebryn
You can get a plain JS object (or hash) from an Ember.Object
instance by calling getProperties()
with a list of keys.
您可以Ember.Object
通过getProperties()
使用键列表调用从实例中获取普通 JS 对象(或哈希)。
If you want it as a string, you can use JSON.stringify()
.
如果你想要它作为一个字符串,你可以使用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"}'
回答by Georg
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.
我也一直在为此苦苦挣扎。正如 Mirko 所说,如果您将 ember 对象传递给 JSON.stringify,您将收到循环引用错误。但是,如果您将对象存储在一个属性中并在该对象上使用 stringify,它就可以工作,即使是嵌套的子属性也是如此。
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.
但是,这只适用于 Chrome、Safari 和 Firefox。在 IE8 中,我得到了堆栈溢出,所以这不是一个可行的解决方案。
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.
我求助于在我的对象模型上创建 JSON 模式,并编写了一个递归函数来使用模式中的属性迭代对象,然后构造纯 Javascript 对象,然后我可以将其字符串化并发送到我的服务器。我也使用模式进行验证,所以这个解决方案对我来说效果很好,但如果你有非常大的动态数据模型,这是不可能的。我也对更简单的方法感兴趣。
回答by Kevin Pauli
I modifed @pangratz solution slightly to make it handle nested hierarchies of Jsonables:
我稍微修改了 @pangratz 解决方案以使其处理 Jsonables 的嵌套层次结构:
App.Jsonable = Ember.Mixin.create({
getJson: function() {
var v, json = {};
for (var key in this) {
if (this.hasOwnProperty(key)) {
v = this[key];
if (v === 'toString') {
continue;
}
if (Ember.typeOf(v) === 'function') {
continue;
}
if (App.Jsonable.detect(v))
v = v.getJson();
json[key] = v;
}
}
return json;
}
});
回答by ecairol
App.io.emit('node', {node: node.toJSON()});
App.io.emit('node', {node: node.toJSON()});
Or if you have an ID property and want to include it:
或者,如果您有一个 ID 属性并希望包含它:
App.io.emit('node', {node: node.toJSON({includeId: true})});
App.io.emit('node', {node: node.toJSON({includeId: true})});
回答by jennas
I've written an extensive article on how you can convert ember models into native objects or JSON which may help you or others :)
我写了一篇关于如何将 ember 模型转换为原生对象或 JSON 的广泛文章,这可能对您或其他人有帮助:)
http://pixelchild.com.au/post/44614363941/how-to-convert-ember-objects-to-json
http://pixelchild.com.au/post/44614363941/how-to-convert-ember-objects-to-json
回答by mkoistinen
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:
这false
是可选的,但如果您不打算修改任何属性,则性能会更高,根据您的问题就是这种情况。这对我有用,但我担心 Ember.meta 是一种私有方法,可能会以不同的方式工作,甚至在未来的版本中都不可用。(尽管 Ember.getMeta() 是否是私有的,我并不清楚)。您可以在此处以最新的源代码形式查看它:
https://github.com/emberjs/ember.js/blob/master/packages/ember-metal/lib/utils.js
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:
该values
属性仅包含“正常”属性。您可以从Ember.meta( App.node, false ).cached
. 因此,如果您在构建中使用 jQuery,您可以轻松地合并这两个对象,如下所示:
$.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.
遗憾的是,我还没有找到一种以这种方式获取像数组属性这样的子结构的方法。
回答by Leo
I modified @Kevin-pauli solution to make it works with arrays as well:
我修改了 @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;
}
});
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:
我还做了一些进一步的修改,以获得两全其美的效果。在以下版本中,我检查 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;
}
});
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!
感谢@pangratz 和@Kevin-Pauli 的解决方案!
回答by Klaus
Here I take @leo, @pangratz and @kevin-pauli solution a little step further. Now it iterates not only with arrays but also through has manyrelationships, it doesn't check if a value has the type Arraybut it calls the isArrayfunction defined in Ember's API.
在这里,我将@leo、@pangratz 和 @kevin-pauli 解决方案更进一步。现在它不仅使用数组进行迭代,而且还通过许多关系进行迭代,它不检查值是否具有Array类型,而是调用Ember 的 API 中定义的isArray函数。
Coffeescript
咖啡脚本
App.Jsonable = Em.Mixin.create
getJson: ->
jsonValue = (attr) ->
return attr.map(jsonValue) if Em.isArray(attr)
return attr.getJson() if App.Jsonable.detect(attr)
attr
base =
if Em.isNone(@get('jsonProperties'))
# no list given: let's use all the properties
this
else
# the object has a selective list of properties to inspect
@getProperties(@get('jsonProperties'))
hash = {}
for own key, value of base
continue if value is 'toString' or Em.typeOf(value) is 'function'
json[key] = jsonValue(value)
json
Javascript
Javascript
var hasProp = {}.hasOwnProperty;
App.Jsonable = Em.Mixin.create({
getJson: function() {
var base, hash, hashValue, key, value;
jsonValue = function(attr) {
if (Em.isArray(attr)) {
return attr.map(jsonValue);
}
if (App.Jsonable.detect(attr)) {
return attr.getJson();
}
return attr;
};
base = Em.isNone(this.get('jsonProperties')) ? this : this.getProperties(this.get('jsonProperties'));
json = {};
for (key in base) {
if (!hasProp.call(base, key)) continue;
value = base[key];
if (value === 'toString' || Em.typeOf(value) === 'function') {
continue;
}
json[key] = jsonValue(value);
}
return json;
}
});
回答by Shimon Doodkin
I have:
我有:
- fixed and simplified code
- added circular reference prevention
- added use of get of value
removed all of the default properties of an empty component
//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:"" }) */
- 固定和简化的代码
- 添加了循环引用预防
- 附加使用 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:"" }) */