Javascript 将带有符号的ES6类转换为JSON

Javascript 将带有符号的ES6类转换为JSON,javascript,json,ecmascript-6,aurelia,Javascript,Json,Ecmascript 6,Aurelia,我有硬编码类来表示我的Aurelia应用程序中的模型。这是一个“后期编辑”模型: var _postID = Symbol(); var _title = Symbol(); var _text = Symbol(); export class PostEdit { constructor(postEdit) { this[_postID] = postEdit.postID; this.title = postEdit.title;

我有硬编码类来表示我的Aurelia应用程序中的模型。这是一个“后期编辑”模型:

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; }

}
操作对象后,我需要
将其放回服务器,然后
将其放回服务器。但是它看起来像是
Aurelia
HttpClient
正在发送一个空的
JSON
字符串(
{}
)。仔细观察,在将ES6类转换为
JSON
时,似乎忽略了
符号


如何将我的所有属性放入
JSON
字符串以提交回服务器?

我假设您使用符号来保持数据的私有性,但这意味着您必须执行一些额外的步骤,如果您希望数据包含在JSON表示中

下面是一个在模型上使用
toJSON
显式导出您关心的属性的示例

export class PostEdit {

  // ...
  toJSON() {
    return {
      postID: this.postID,
      title:  this.title,
      text:   this.text
    };
  }
}


在您的实例上调用
JSON.stringify
时,它将自动调用
toJSON
为您的类指定一个
toJSON
方法,该方法返回可stringify的对象:

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
        };
    }
}
将自动调用该函数并用结果替换您的实例

另外,您可能希望向类中添加一个
fromJSON
方法,可以在
JSON.parse
期间使用该方法来恢复实例。在您的情况下,这是微不足道的:

    static fromJSON(obj) {
        return new this(obj);
    }

但在其他类中可能需要更复杂的东西。

基于符号的私有变量是ES6中封装的一个重要方法。JS中的封装很少是合理的,但是这些是导致问题的访问器(不是符号)

访问器在ES6类中。因此,属性不是在实例上定义的,而是在原型上定义的,它是不可枚举的。它可以在传输代码中看到,或者通过检查

postEditInstance.hasOwnProperty('postID') === false
Object.getPrototypeOf(postEditInstance).hasOwnProperty('postID') === true
Object.getPrototypeOf(postEditInstance).propertyIsEnumerable('postID') === false
另一方面,stringify
,序列化对象


解决方案是使用方法根据所需的条件序列化对象。或者在模型的访问器上使用Occam的razor,特别是在它们不是关键的情况下。

我想使用
object.assign将整个类分配给一个对象。

我最初的观点是在将分配的类分配给对象的类上使用它。这在chrome中为
\u json
创建了一个无限循环。坏主意

class test {
    constructor() {
        this._json = {type: 'map'};
        Object.assign(this, this._json);
    }
    toJSON(){
        Object.assign(this._json, this);
        return this._json;
    }
}
我必须排除
\ujson
变量,所以我迭代类变量以排除它

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;
    }
}
但奇怪的是,即使没有
if(i!==''ujson')


尚未对其进行全面测试,但我认为这将是一个很好的共享。

要获得更动态的解决方案,请使用以下内容:

export class MeMe(){
 toJSON() {
    return Object.getOwnPropertyNames(this).reduce((a, b) => {
      a[b] = this[b];
      return a;
    }, {});
  }
}
或者您可以使用我的:)


您希望它们在JSON表示中是什么样子?JSON对象属性看起来像
“name”:“value”
,但是
符号应该使用什么名称呢?有关JSON中可以表示的值的类型,请参见www.JSON.org。您可能需要在类中提供一个
toJSON
方法来返回所需的表示形式。@Barmar最后我需要
{“postID”:“1”…}
。我想我希望有一些内在的方法来做到这一点,为什么你需要接球手和二传手?他们不会做任何事情,除非你使用普通财产。@Jonesopolis:绝对是过火了。如果在getter/setter主体中添加验证或解析或其他内容,则可以使用它们,但如果只是分配/访问“更私有”的属性,则几乎没有用处。顺便说一句,符号不是私有的,它们只是隐藏在普通循环或类似于
JSON.stringify
的东西中不被枚举。他们仍然可以被任何人访问。优雅的解决方案。
export class MeMe(){
 toJSON() {
    return Object.getOwnPropertyNames(this).reduce((a, b) => {
      a[b] = this[b];
      return a;
    }, {});
  }
}
import json from "json-decorator";  

@json("postID") // pass the property names that you want to ignore
export class MeMe(){
  // ...
}