[英]Convert ES6 Class with Symbols to JSON
我有硬編碼類來表示我的 Aurelia 應用程序中的模型。 這是一個 model '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; }
}
object 操作完成后,我需要將其PUT
和POST
回服務器。 但看起來Aurelia
的HttpClient
正在發送一個空的JSON
字符串 ( {}
)。 仔細觀察,似乎在將 ES6 class 轉換為JSON
時忽略了Symbols
。
我 go 如何將我的所有屬性放入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
為您的類提供一個返回stringifyable對象的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);
}
但是你可能需要在其他課程中更復雜的東西。
更動態的解決方案使用此:
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(){
// ...
}
基於符號的私有變量是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
中的_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
被忽略
沒有完全測試它,但我認為這將是一個很好的分享。
我 go 如何將我的所有(符號)屬性轉換為 JSON 字符串以提交回服務器?
要獲取所有交易品種屬性,您可以使用Object.getOwnPropertySymbols()獲取直接在給定 object 上找到的所有交易品種屬性的數組。例如:
const pe = new PostEdit({...});
const symbols = Object.getOwnPropertySymbols(pe);
但是,由於 PostEdit 的所有三個符號屬性都使用空描述( new Symbol()
,沒有任何描述參數),因此無法區分這三個符號。 如果上面的symbols
數組被打印出來,你會得到:
//console.log(symbols)
[ Symbol(), Symbol(), Symbol() ]
因此,如果您想序列化/反序列化 PostEdit 實例而不向PostEdit
class 添加toJSON()
/ fromJSON()
方法,您可以為符號提供有意義的描述,然后相應地序列化它們:
var _postID = Symbol('postID');
var _title = Symbol('title');
var _text = Symbol('text');
export class PostEdit {
...
}
const pe = new PostEdit({...});
const symbols = Object.getOwnPropertySymbols(pe);
const serializeObj = {};
for (let s of symbols) {
serializeObj[s.description] = pe[s];
}
const serializedText = JSON.stringify(serializeObj);
為了使上述序列化/反序列化步驟更方便使用,並解決相同符號描述問題,我制作了一個名為esserializer的 npm 模塊,並在其專業版中實現了這些邏輯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.