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; }
}
オブジェクトを操作した後、PUT
とPOST
をサーバーに戻す必要があります。しかし、Aurelia
のHttpClient
が空のJSON
文字列({}
)。調べてみると、ES6クラスをSymbols
に変換するときにJSON
が無視されるようです。
すべてのプロパティをJSON
文字列に入れてサーバーに送信するにはどうすればよいですか?
データをプライベートに保つためにシンボルを使用していると想定していますが、これは、そのデータを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
が呼び出されます
より動的なソリューションの場合、これを使用します:
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(){
// ...
}
文字列化可能なオブジェクトを返す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);
}
しかし、他のクラスではもっと複雑なものが必要になるかもしれません。
シンボルベースのプライベート変数は、ES6でカプセル化するためのかなりのレシピです。 JSでのカプセル化はめったに正当化されませんが、これらはここで問題を引き起こす(シンボルではなく)アクセサーです。
ES6クラスでは、アクセサは プロトタイプメソッド です。したがって、プロパティはインスタンスではなくプロトタイプで定義され、列挙できません。トランスパイルされたコードで確認できます。
postEditInstance.hasOwnProperty('postID') === false
Object.getPrototypeOf(postEditInstance).hasOwnProperty('postID') === true
Object.getPrototypeOf(postEditInstance).propertyIsEnumerable('postID') === false
一方、JSON.stringify
は、オブジェクトの 独自の列挙可能なプロパティのみ をシリアル化します。
解決策は、 toJSON メソッドを使用して、望ましい条件に従ってオブジェクトをシリアル化することです。または、特にそれらが重要ではない場合は、モデルのアクセサーにOccamのかみそりを使用します。
_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
_は無視されます
完全にはテストしていませんが、これは良いシェアになると思いました。