web-dev-qa-db-ja.com

シンボルを含むES6クラスをJSONに変換する

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をサーバーに戻す必要があります。しかし、AureliaHttpClientが空のJSON文字列({})。調べてみると、ES6クラスをSymbolsに変換するときにJSONが無視されるようです。

すべてのプロパティをJSON文字列に入れてサーバーに送信するにはどうすればよいですか?

9
Jonesopolis

データをプライベートに保つためにシンボルを使用していると想定していますが、これは、そのデータを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が呼び出されます

19
Thank you

より動的なソリューションの場合、これを使用します:

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(){
  // ...
}
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 は自動的にそれを呼び出し、インスタンスを結果に置き換えます。

また、JSON.parse中にインスタンスを復活させるために使用できるfromJSONメソッドをクラスに追加することもできます。あなたの場合それは取るに足らないです:

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

しかし、他のクラスではもっと複雑なものが必要になるかもしれません。

6
Bergi

シンボルベースのプライベート変数は、ES6でカプセル化するためのかなりのレシピです。 JSでのカプセル化はめったに正当化されませんが、これらはここで問題を引き起こす(シンボルではなく)アクセサーです。

ES6クラスでは、アクセサは プロトタイプメソッド です。したがって、プロパティはインスタンスではなくプロトタイプで定義され、列挙できません。トランスパイルされたコードで確認できます。

postEditInstance.hasOwnProperty('postID') === false
Object.getPrototypeOf(postEditInstance).hasOwnProperty('postID') === true
Object.getPrototypeOf(postEditInstance).propertyIsEnumerable('postID') === false

一方、JSON.stringifyは、オブジェクトの 独自の列挙可能なプロパティのみ をシリアル化します。

解決策は、 toJSON メソッドを使用して、望ましい条件に従ってオブジェクトをシリアル化することです。または、特にそれらが重要ではない場合は、モデルのアクセサーにOccamのかみそりを使用します。

3
Estus Flask

_Object.assign_を使用して、クラス全体をオブジェクトに割り当てたい

割り当てられたクラスをオブジェクトに割り当てるクラスでこれを使用する私の最初の視点。これにより、クロームで__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;
    }
}
_

しかし、奇妙なことに、if(i !== '_json')がなくても__json_は無視されます

完全にはテストしていませんが、これは良いシェアになると思いました。

0
Martijn Mellens