簡體   English   中英

將帶符號的 ES6 Class 轉換為 JSON

[英]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 操作完成后,我需要將其PUTPOST回服務器。 但看起來AureliaHttpClient正在發送一個空的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM