Как преобразовать экземпляр класса TypeScript с помощью getter / setter в JSON для хранения в базе данных MySQL - PullRequest
1 голос
/ 12 апреля 2020

У меня есть следующий класс TypeScript, который содержит метод получения / установки:

export class KitSection {

    uid: string;
    order: number;

    set layout(layout: KitLayout) {
        this._layout = new KitLayout(layout);
    }

    get layout() {
        return this._layout;
    }

    private _layout: KitLayout;

    constructor(init?: Partial<KitSection>) {
        Object.assign(this, init);
    }

}

// I can create an instance like so:
const section = new KitSection(data);

Мне нужно POST этот экземпляр на моем сервере в качестве объекта JSON для хранения в базе данных MySQL столбец типа: JSON, поэтому я решил, что могу сделать следующее:

const jsonSection = JSON.parse(JSON.stringify(section))

Это создает объект JSON, но когда я проверяю в консоли, я вижу свою частную переменную getter / setter вместо переменной publi c в объекте:

console.log(jsonSection);

///IN CONSOLE///

uid: "a"
order: 0
_layout: {_rows: Array(2), columns: 12}

Я не хочу хранить личную переменную _layout в моей базе данных, мне нужно сохранить аналог publi c, определенный в метод получения / установки: layout.

Далее я проверил ответ, приведенный здесь: { ссылка }, где предлагается добавить следующий метод для преобразования в JSON:

public toJSON(): string {
    let obj = Object.assign(this);
    let keys = Object.keys(this.constructor.prototype);
    obj.toJSON = undefined;
    return JSON.stringify(obj, keys);
}

Однако это возвращает пустой объект. При проверке, когда я console.log() * this.constructor.prototype, я вижу все свойства объекта, но каждый объект является своего рода серым, поэтому, когда мы используем Object.keys(), я получаю пустой массив. Почему эти свойства конструктора неактивны?

1 Ответ

0 голосов
/ 12 апреля 2020

JSON.stringify будет только перебирать собственные перечисляемые свойства. Здесь, так как layout является свойством объекта прототипа , а не самого экземпляра, когда вы пытаетесь структурировать экземпляр, метод получения не вызывается. (но поскольку _layout является собственным перечисляемым свойством, оно означает , включенное в результат)

Аналогично, следующий строковый объект пуст:

const obj = Object.create({
  get prop() {
    return 'val';
  }
});
console.log(JSON.stringify(obj));

Вы можете исправить это, поместив геттер непосредственно в экземпляр и сделав _layout не перечисляемым. Таким образом, при строковом преобразовании будет вызван метод получения, но _layout не будет включен:

export class KitSection {

    uid: string;
    order: number;

    private _layout: KitLayout;

    constructor(init?: Partial<KitSection>) {
        Object.defineProperty(
            this,
            'layout',
            {
                enumerable: true,
                get() {
                    return this._layout;
                },
                set(newVal) {
                    this._layout = new KitLayout(newVal);
                }
            }
        );
        Object.defineProperty(
            this,
            '_layout',
            {
                enumerable: false,
                value: undefined,
            }
        );
        Object.assign(this, init);
    }
}

const section = new KitSection(data);

Это будет выглядеть немного яснее, если вместо этого вы используете синтаксис поля частного класса:

export class KitSection {
    #layout: KitLayout | undefined;
    constructor(init?: Partial<KitSection>) {
        Object.defineProperty(
            this,
            'layout',
            {
                enumerable: true,
                get() {
                    return this.#layout;
                },
                set: (newVal) => {
                    this.#layout = new KitLayout(newVal);
                }
            }
        );
        Object.assign(this, init);
    }
}

Вы также можете вызвать геттер вручную.

Если KitLayout по существу сериализуем, чтобы превратить сериализованный объект обратно в экземпляр KitSection, KitLayout или один из его вспомогательных методов должен быть в состоянии превратить сериализованный KitLayout в экземпляр. Либо снова передайте его через конструктор (просто вызовите new KitSection, который передает его KitLayout), либо отделите layout от десериализованного объекта и используйте отдельный метод для KitSection, который вызывает помощник KitLayout Метод и присваивает приватное свойство, может быть что-то вроде:

integrateLayout(layoutInfo) {
  this.#layout = KitLayout.makeKitLayoutFromLayoutInfo(layoutInfo)
}

, где layoutInfo - простой объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...