TypeScriptを使用していくつかのクラスを定義しています。プロパティを作成すると、次のplunkrにClass1
と同等のものが生成されます。
http://plnkr.co/edit/NXUo7zjJZaUuyv54TD9i?p=preview
var Class1 = function () {
this._name = "test1";
}
Object.defineProperty(Class1.prototype, "Name", {
get: function() { return this._name; },
set: function(value) { this._name = value; },
enumerable: true
});
JSON.stringify(new Class1()); // Will be "{"_name":"test1"}"
シリアル化するとき、定義したプロパティは出力されません。
instance2
とinstance3
は、定義されたプロパティをシリアル化することで期待どおりに動作します。 (plunkrの出力を参照してください)。
私の実際の質問は:これは正常ですか?
もしそうなら、どうすれば最も効率的な方法でそれを回避できますか?
プロトタイプで toJSON()
メソッドを定義して、インスタンスのシリアル化方法をカスタマイズできます。
Class1.prototype.toJSON = function () {
return {
Name: this.Name
};
};
JSON.stringify(new Class1()); // Will be '{"Name":"test1"}'
プッシュしたい場合は、TypeScriptのデコレータ提案を試してください。
この提案によると( https://github.com/wycats/javascript-decorators ):
デコレータは:
それはこのようになります(高レベルのビュー):
クライアントコード:
@serializable()
class Person {
constructor(name: string) {
this._name = name;
}
private _name: string;
@serialize()
get name() {
return this._name;
}
@serialize('Language')
get lang() {
return 'JavaScript';
}
}
インフラ:
const serialized = new WeakMap();
export function serializable(name?: string) {
return function (target, propertyKey, descriptor) {
target.prototype.toJSON = function () {
const map = serialized.get(target.prototype);
const props = Object.keys(map);
return props.reduce((previous, key) => {
previous[map[key]] = this[key];
return previous;
}, {});
}
}
}
export function serialize(name?: string) {
return function (target, propertyKey, descriptor) {
let map = serialized.get(target);
if (!map) {
map = {};
serialized.set(target, map);
}
map[propertyKey] = name || propertyKey;
}
}
[〜#〜] update [〜#〜]:このサンプルデコレータを https://github.comのリポジトリに抽出しました/ awerlang/es-decorators
はい、仕様です。
ECMAで定義されているように、シリアル化されるのは独自の列挙可能なプロパティだけです(stringify()
はObject.keys()
の観点から定義されています)。
プロパティアクセサーは、TypeScriptとES6の両方のプロトタイプで定義されます。
そして、あなたの最後の質問に答えてください、それはこの操作を実行する最も効率的な方法です。
それ以外には、a)シリアル化の各オブジェクト部分にtoJSON()を定義するか、またはb)置換関数/配列をJSON.stringify()の2番目の引数として渡すだけです。
プロトタイプのホワイトリストプロパティ:
JSON.stringify(instance, Object.keys(instance.constructor.prototype))
ここに何かを置くと、他の人を助けることができます。 JSON.stringifyがプロトタイプで定義されたプロパティをシリアル化しないのを修正するために私がしていること
var newObject = $.extend(false, {}, orginalObj);
次に、newObjectにプロトタイププロパティの代わりにインスタンスプロパティがあることに気付きました。 TypeScriptを使用してアクセサーを取得しています。
あなたが発見したように、それはプロトタイプで定義されたプロパティをシリアル化しません。
私はそれが理想的でないことを知っていますが、別のオプションはこれを行うことです:
class Class1 {
private _name = "test1";
Name: string; // do this to make the compiler happy
constructor() {
Object.defineProperty(this, "Name", {
get: function() { return this._name; },
set: function(value) { this._name = value; },
enumerable: true
});
}
}
インスタンスのプロパティを定義すると、プロパティがシリアル化されます。