2015-10-28 1 views
4

У меня есть жестко заданные классы для представления моделей в моем приложении Aurelia. Вот модель «PostEdit»:Преобразование класса ES6 с символами в JSON

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 его обратно на сервер. Но это похоже на AureliaHttpClient сбрасывает JSON строку ({}). При взгляде на него, кажется, что Symbols игнорируются при преобразовании класса ES6 в JSON.

Как я могу получить все свои свойства в строку JSON, чтобы отправить обратно на сервер?

+0

Что вы ждете, чтобы они выглядели, как в представлении JSON? Свойства объекта JSON выглядят как '" name ":" value "', но какое имя будет использоваться для символа 'Symbol'? – Barmar

+0

См. Www.json.org для типов значений, которые могут быть представлены в JSON. Вероятно, вам нужно предоставить метод 'toJSON' в вашем классе, чтобы вернуть желаемое представление. – Barmar

+0

@ Barmar в конце мне нужно '{" postID ":" 1 "...}'. Думаю, я надеялся на какой-то встроенный способ сделать это. – Jonesopolis

ответ

13

Я предполагаю, что вы используете символы для хранения данных конфиденциальными, но это означает, что вам нужно будет пройти дополнительные шаги, если вы хотите, чтобы эти данные были включены в представление 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

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 будет автоматически вызывать это и заменить ваш экземпляр на результат.

Также вы можете добавить метод fromJSON к вашему классу, который вы можете использовать для восстановления экземпляров во время JSON.parse. В вашем случае тривиально:

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

, но вам может понадобиться что-то более сложное в других классах.

3

Собственные переменные на основе символов являются значительным рецептом для инкапсуляции в ES6. Инкапсуляция в JS редко оправдана, но это аксессоры (а не символы), которые вызывают проблемы здесь.

Аксессуар prototype methods в классах ES6. Таким образом, свойство определяется не на экземпляре, а на прототипе, оно не перечислимо. Это можно увидеть в transpiled коде, или путем проверки

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

JSON.stringify, с другой стороны, упорядочивает only own enumerable properties объекта.

Решение заключается в использовании метода toJSON для сериализации объекта в соответствии с желаемыми условиями. Или использовать бритву Оккама на аксессуарах модели, особенно если они не имеют решающего значения.

0

Я хотел бы иметь весь класс, присвоенный объекту с помощью 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; 
    } 
} 

но достаточно удачливый _json игнорируется даже без if(i !== '_json')

не полностью протестированы, но я думал, что это будет хорошая доля.

0

для более динамичного решения этого:

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(){ 
    // ... 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^