Javascript 将带有符号的 ES6 类转换为 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33382939/
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
Convert ES6 Class with Symbols to JSON
提问by Jonesopolis
I have hardcoded classes to represent models in my Aurelia application. Here's a model 'PostEdit':
我有硬编码的类来表示我的 Aurelia 应用程序中的模型。这是一个模型“PostEdit”:
var _postID = Symbol();
var _title = Symbol();
var _text = Symbol();
export class PostEdit {
constructor(postEdit) {
this[_postID] = postEdit.postID;
this.title = postEdit.title;
this.text= postEdit.text;
}
get postID() { return this[_postID]; }
get title() { return this[_title]; }
set title(val) { this[_title] = val; }
get text() { return this[_text]; }
set text(val) { this[_text] = val; }
}
After the object is manipulated, I need to PUT
and POST
it back to the server. But it looks like Aurelia
's HttpClient
is sending an empty JSON
string ({}
). Looking into it, it seems that Symbols
are ignored when converting an ES6 class to JSON
.
该对象被操纵后,我需要PUT
和POST
它回服务器。但看起来Aurelia
'sHttpClient
正在发送一个空JSON
字符串 ( {}
)。调查它,似乎Symbols
在将 ES6 类转换为JSON
.
How can I go about getting all my properties into a JSON
string to submit back to the server?
如何将我的所有属性放入一个JSON
字符串中以提交回服务器?
回答by Thank you
I'm assuming you're using symbols to keep the data private, but this means you're going to have to go through some extra steps if you want that data included in the JSON representation.
我假设您使用符号来保持数据的私密性,但这意味着如果您希望将数据包含在 JSON 表示中,您将不得不执行一些额外的步骤。
Here's an example using toJSON
on your model to explicitly export the properties you care about
这是toJSON
在您的模型上使用以显式导出您关心的属性的示例
export class PostEdit {
// ...
toJSON() {
return {
postID: this.postID,
title: this.title,
text: this.text
};
}
}
Or
或者
export class PostEdit {
// ...
toJSON() {
let {postID, title, text} = this;
return {postID, title, text};
}
}
When JSON.stringify
is called on your instance, it will automatically call toJSON
当JSON.stringify
在您的实例上调用时,它会自动调用toJSON
回答by Fareed Alnamrouti
for more dynamic solution use this:
对于更动态的解决方案,请使用:
export class MeMe(){
toJSON() {
return Object.getOwnPropertyNames(this).reduce((a, b) => {
a[b] = this[b];
return a;
}, {});
}
}
or you can use my json-decorator:)
或者你可以使用我的json-decorator:)
import json from "json-decorator";
@json("postID") // pass the property names that you want to ignore
export class MeMe(){
// ...
}
回答by Bergi
Give your class a toJSON
method that returns a stringifyable object:
为您的类提供一个toJSON
返回可字符串化对象的方法:
export class PostEdit {
constructor(postEdit) {
this[_postID] = postEdit.postID;
this.title = postEdit.title;
this.text = postEdit.text;
}
get postID() { return this[_postID]; }
get title() { return this[_title]; }
set title(val) { this[_title] = val; }
get text() { return this[_text]; }
set text(val) { this[_text] = val; }
toJSON() {
return {
postId: this.postId,
title: this.title,
text: this.text
};
}
}
JSON.stringify
will automatically call that and replace your instance with the result.
JSON.stringify
将自动调用它并用结果替换您的实例。
Also you might want to add a fromJSON
method to your class that you can use to revive instances during JSON.parse
. It is trivial in your case:
此外,您可能希望向fromJSON
您的类添加一个方法,您可以使用该方法在JSON.parse
. 在你的情况下这是微不足道的:
static fromJSON(obj) {
return new this(obj);
}
but you might need something more complicated in other classes.
但是您可能需要在其他类中更复杂的东西。
回答by Estus Flask
Symbol-based private variables are considerable recipe for encapsulation in ES6. The encapsulation in JS is rarely justified, but these are accessors (not symbols) that cause problems here.
基于符号的私有变量是 ES6 封装的重要方法。JS 中的封装很少被证明是合理的,但这些是导致问题的访问器(而不是符号)。
Accessors are prototype methodsin ES6 classes. So the property is defined not on instance but on prototype, it is non-enumerable. It can be seen in transpiled code, or by checking
访问器是ES6 类中的原型方法。所以属性不是在实例上定义的,而是在原型上定义的,它是不可枚举的。它可以在转译的代码中看到,或者通过检查
postEditInstance.hasOwnProperty('postID') === false
Object.getPrototypeOf(postEditInstance).hasOwnProperty('postID') === true
Object.getPrototypeOf(postEditInstance).propertyIsEnumerable('postID') === false
JSON.stringify
, on the other hand, serializes only own enumerable propertiesof the object.
JSON.stringify
,另一方面,仅序列化对象自己的可枚举属性。
The solution is to use toJSONmethod to serialize the object according to the desirable conditions. Or to use Occam's razor on model's accessors, especially if they aren't crucial there.
解决方案是使用toJSON方法根据需要的条件序列化对象。或者在模型的配件上使用奥卡姆剃刀,特别是如果它们在那里并不重要。
回答by Martijn Mellens
I wanted to have the whole class assigned to an object using Object.assign
我想将整个班级分配给一个对象使用 Object.assign
My initial perspective on using this on a class assigning the allocated class to object. This created an infinite loop for _json
in chrome. Bad idea.
我对在将分配的类分配给对象的类上使用它的最初看法。这_json
在 chrome 中创建了一个无限循环。馊主意。
class test {
constructor() {
this._json = {type: 'map'};
Object.assign(this, this._json);
}
toJSON(){
Object.assign(this._json, this);
return this._json;
}
}
I had to exclude the _json
variable, so I iterated over the class variables to exclude it.
我不得不排除_json
变量,所以我遍历类变量以排除它。
class test2 {
constructor() {
this._json = {type: 'map'};
Object.assign(this, this._json);
}
toJSON(){
Object.assign(this._json, {
conv() {
let ret = {};
for(let i in this )
{
if(i !== '_json')
ret[i] = this[i];
}
return ret;
}
} );
return this._json;
}
}
but weirdly enough _json
gets ignored even without if(i !== '_json')
但奇怪的是_json
即使没有if(i !== '_json')
have not fully tested it, but I thought this would be a good share.
还没有完全测试它,但我认为这将是一个很好的分享。