将带符号的ES6类转换为JSON

时间:2015-10-28 04:31:04

标签: javascript json ecmascript-6 aurelia

我有硬编码的类来表示我的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; }

}

操作对象后,我需要PUTPOST将其返回给服务器。但看起来Aurelia HttpClient发送一个空的JSON字符串({})。调查一下,将ES6类转换为Symbols时似乎忽略了JSON

如何将所有属性转换为JSON字符串以提交回服务器?

5 个答案:

答案 0 :(得分:17)

我假设您正在使用符号来保持数据的私密性,但这意味着如果您希望JSON表示中包含这些数据,您将不得不经历一些额外的步骤。

以下是使用模型上的toJSON明确导出您关注的属性的示例

export class PostEdit {

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

或者

export class PostEdit {

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

在您的实例上调用JSON.stringify时,它会自动调用toJSON

答案 1 :(得分:6)

为您的类提供一个返回字符串化对象的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会自动调用该内容,并将结果替换为您的实例。

此外,您可能希望在类中添加fromJSON方法,以便在JSON.parse期间恢复实例。在你的情况下这是微不足道的:

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

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

答案 2 :(得分:4)

更多动态解决方案使用此:

export class MeMe(){
 toJSON() {
    return Object.getOwnPropertyNames(this).reduce((a, b) => {
      a[b] = this[b];
      return a;
    }, {});
  }
}

或者您可以使用我的json-decorator:)

import json from "json-decorator";  

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

答案 3 :(得分:3)

基于符号的私有变量是ES6中封装的重要配方。 JS中的封装很少被证明是合理的,但这些是在这里引起问题的访问器(而不是符号)。

ES6课程中的访问者为prototype methods。因此,属性不是在实例上定义,而是在原型上定义,它是不可枚举的。它可以在转换后的代码中看到,也可以通过检查

来查看
postEditInstance.hasOwnProperty('postID') === false
Object.getPrototypeOf(postEditInstance).hasOwnProperty('postID') === true
Object.getPrototypeOf(postEditInstance).propertyIsEnumerable('postID') === false
另一方面,

JSON.stringify序列化对象的only own enumerable properties

解决方案是使用toJSON方法根据所需条件序列化对象。或者在模型的存取器上使用奥卡姆剃刀,特别是如果它们在那里不重要的话。

答案 4 :(得分:0)

我希望使用Object.assign

将整个类分配给对象

我在将类分配给对象的类上使用它的初步观点。这为chrome中的_json创建了一个无限循环。不好的主意。

class test {
    constructor() {
        this._json = {type: 'map'};
        Object.assign(this, this._json);
    }
    toJSON(){
        Object.assign(this._json, this);
        return this._json;
    }
}

我必须排除_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;
    }
}

但即使没有_json

,奇怪的if(i !== '_json')也会被忽略

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