Methods for transforming a TypeScript class instance containing getter/setter properties into a JSON format for storage within a MySQL database

I am currently working on a TypeScript class that includes a getter and setter method:

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);
    }

}

// An instance can be created like this:
const section = new KitSection(data);

The task at hand is to send this instance as a JSON object with a POST request to the server for storage in a MySQL database column of type JSON. The initial approach was to use:

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

Although this successfully creates a JSON object, upon inspection in the console, the private getter/setter variable is displayed instead of the public variable within the object:

console.log(jsonSection);

///IN CONSOLE///

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

To avoid storing the private variable _layout in the database, it is essential to store its public counterpart defined in the getter/setter as layout.

An alternative solution from this answer proposes adding a method to convert to JSON:

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

However, this implementation results in an empty object. Upon investigation by logging this.constructor.prototype, all properties are visible but appear greyed out, leading to an empty array when used with Object.keys(). The question remains - why are these constructor properties greyed out?

Answer №1

JSON.stringify works by iterating only over the own enumerable properties of an object. In this case, if a property like layout is part of the prototype object rather than the instance itself, the getter associated with it will not be invoked when stringifying the instance. However, if the property _layout is an own enumerable property, it will be included in the result.

An example illustrating this behavior is where the resulting stringified object appears empty:

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

A possible solution to address this issue is by placing the getter directly on the instance and by ensuring that the _layout property is non-enumerable. This modification ensures that the getter will be invoked during stringification, while preventing the inclusion of _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);

For improved readability, using private class fields syntax provides a neater representation:

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);
}
}

Additionally, you can manually invoke the getter method if required.

If the serialization of KitLayout is essential, for reinstating the serialized object as a KitSection instance, either the constructor or a helper method within KitLayout should facilitate the transformation. By passing the serialized data through the constructor again or a specific method like integrateLayout, the private property can be properly set up:

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

In this scenario, layoutInfo refers to the plain object containing the serialized data.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Displaying a collection of objects in HTML by iterating through an array

As someone new to coding, I am eager to tackle the following challenge: I have designed 3 distinct classes. The primary class is the Place class, followed by a restaurant class and an events class. Both the restaurant class and events class inherit core p ...

Prevent a <span> element from affecting the linking functionality of an <a> tag

Is it possible to make a hyperlink clickable without including the <span> tags within it and instead attaching a jQuery event to those tags? This is the code I'm using. It utilizes bootstrap's list-group for a navigation element: <ul cl ...

Unable to establish breakpoints in TypeScript within VS Code

I seem to be facing an issue while trying to set breakpoints in my TypeScript nodejs app using Visual Studio Code. Despite following the guidelines provided on the Visual Studio Code website, I have not been able to achieve success. Below is the content o ...

Supabase's newly uploaded audio blobs are experiencing difficulties when it comes to

I've integrated Supabase storage for storing audio blobs. After retrieving the blob from an API call, it is uploaded successfully to the storage bucket. However, when attempting to play the audio file, nothing happens and the duration shows as 0:00. S ...

Sometimes jQuery may require multiple executions with just one click

Content of index.php <script type="text/javascript" src="//<?php echo $_SERVER["SERVER_NAME"];?>/javascript/jquery-1.10.2.min.js" ></script> <script type="text/javascript"> $(document).ready(function() { $( document ).on( 'c ...

The combination of select2 and jsonform is not functioning properly

I am having trouble rendering multiple select2 with JSON form. $('#resource-form').jsonForm({ schema: { rest: { type: 'object', properties: { template_id: { type: "array", items: { ...

Verify whether the JSON file has an empty string within a bash script

Greetings, the structure of my Json file is as demonstrated below: { "num_sensor" : 1, "J2" : {"B" : "sensor0", "A" : "sensor1", "D" : "sensor2" , "C" : " ...

Can you combine multiple user validation rules with express-validator?

I have a set of rules that are almost similar, except for one where the parameter is optional and the other where it is mandatory. I need to consolidate them so that I can interchangeably use a single code for both cases. Is there a way to merge these rul ...

Difficulty establishing a connection between Typescript and Postgres results in a prolonged

I am attempting to establish a connection to a Postgres database using typescript. For the ORM, I have opted for sequelize-typescript. The issue lies in the fact that the script seems to hang at await sequelize.sync();. Below is the content of the sequeliz ...

Local variables in AngularJS across multiple Angular applications

Looking for a method to retain a local variable not affected by path or angular app changes. Attempted using $window.localStorage.set and get item, rootScope, and $window.variable with no success. ...

Design the parent element according to the child elements

I'm currently working on a timeline project and I am facing an issue with combining different border styles for specific event times. The main challenge is to have a solid border for most of the timeline events, except for a few instances that share a ...

Import resolves Uncaught ReferenceError by preventing access to 'xx' before it is initialized

Currently, I am troubleshooting a peculiar error that has come up. Within my service file where all other services are stored, I have included the import of one component along with all the other services required by the frontend. import { VacationComponen ...

Understanding Pass by Reference within Objects through Extend in Javascript with underscore.js Library

When working with Javascript and using the extend function in the underscore.js library, I am curious about what happens in relation to memory. Consider this example: var obj = {hello: [2]}; var obj2 = {hola: [4]}; _.extend(obj, obj2) obj2.hola = 5; conso ...

SDK for generating templates with JavaScript/jQuery

I am in the process of developing an SDK in JavaScript/jQuery that can generate templates based on user input, such as profile templates and dialog templates. These templates require data from an AJAX call to be created. User input should include certain ...

Encountering build issues in my next.js application post updating to version 12.#.# and implementing Typescript

In my next.js application, I recently upgraded to version 10 and added TypeScript to the mix. Despite ironing out all issues during development, I encountered errors when running yarn next build due to my use of the keyword interface. ./src/components/ ...

combine several arrays next to each other based on a specified key

I have a collection of three sets, each containing three elements: Set1 = [[apple, 2, 4], [banana, 5, 5], [cherry, 4, 1]] Set2 = [[banana, 1, 7], [cherry, 3, 8], [date, 5, 4]] Set3 = [[apple, 5, 2], [banana, 0, 9], ...

How to parse an array in JSON using Swift 3 and iterate through it

Figuring out how to parse JSON data in Swift 3 has been more challenging than I anticipated, especially coming from a Javascript background. Received response from API: [ { "ID": 1881, "image": "myimageURL", }, { "ID": 6333, "image": "myi ...

Encountering difficulties while trying to include js-search in a Vue.js component

My current challenge involves importing the js-search npm module into a Vue component. However, whenever I attempt to do so using: import JsSearch from 'js-search' The subsequent console.log(JsSearch) statement returns undefined. To further in ...

typescript create object with immutable property already set

Can you create an object literal in JavaScript and define its interface with read-only properties simultaneously? For instance let obj = { readonly prop1: 'hello', readonly prop2: 'world' } ...

detect and handle errors when deploying the Node.js function

I'm currently attempting to use code I found on Github to insert data into a Firestore database, but unfortunately, I keep encountering an error. Here's the specific error message: 21:1 error Expected catch() or return promise/catch-or-re ...