Is there a way to transform a complex nested class object into a simple object without losing its methods

Is there a way to convert a deeply nested class object into a plain Object type while still retaining methods like getters and setters?

class A {
    id = "";
    data = {
        sync: {}
    };

}

class SyncService {
    syncResultServiceA = {
        ToSync: 0,
        Synced: 0,
        SyncErrors: [],
    };
    syncResultServiceB = {
        ToSync: 0,
        Synced: 0,
        Errors: [],
    };
}
const a = new A();
a.data.sync = new SyncService();
console.log(a.data.sync.constructor.name) // "SyncService"

I've tried various solutions, like using {...obj} which doesn't work for nested class objects, or using JSON.stringify() + parse() which removes custom methods.

Answer №1

Give this a shot:

class A {
  constructor() {
    this.identifier = '';
    this.content = {
      synchronization: {},
    };
  }

}

class SynchronizationManager {
  constructor() {
    this.syncStatusA = {
      ToSynchronize: 0,
      Synchronized: 0,
      SynchronizationErrors: [],
    };
    this.syncStatusB = {
      ToSynchronize: 0,
      Synchronized: 0,
      Errors: [],
    };
  }
}

const instanceA = new A();
instanceA.content.synchronization = new SynchronizationManager();
console.log(instanceA.content.synchronization.constructor.name) // "SynchronizationManager"

const instanceB = convertToPlainObject(instanceA);
console.log(instanceB.content.synchronization.constructor.name);

function convertToPlainObject(objectClass) {
  const copiedObject = {
    ...objectClass
  };
  for (const [key, value] of Object.entries(copiedObject)) {
    if (typeof value === 'object') {
      copiedObject[key] = convertToPlainObject(value);
    }
  }
  return copiedObject;
}

Answer №2

To tackle all nested objects and convert them, recursion can be employed. Below is a demonstration:

class A {
    identifier = "";
    data = {
        sync: {}
    };

}

class SyncService {
    syncResultServiceA = {
        ToSync: 0,
        Synced: 0,
        SyncErrors: [],
    };
    syncResultServiceB = {
        ToSync: 0,
        Synced: 0,
        Errors: [],
    };
}
const a = new A();
a.data.sync = new SyncService();
console.log(a.data.sync.constructor.name) // "SyncService"

const toPlain = (o) => {
  if (typeof o === 'object' && !Array.isArray(o)) {
    return {...Object.keys(o).reduce((a, c) => (a[c] = toPlain(o[c]), a), {})};
  }
  return o;
}

const plain = toPlain(a);
console.log(plain.data.sync.constructor.name) // "Object"

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

Combining meshes results in a lower frame rate

I have combined approximately 2500 meshes, each with its own color set, but my FPS is lower than if I had not merged them. Based on THIS article, merging is recommended to improve FPS performance. Is there something I am overlooking? var materials = new ...

Creating functionality with a native JavaScript plugin within a directive and test suite

I have a custom JavaScript plugin that is integrated within a directive and utilized in an Angular manner. Snippet of the directive, export default function () { 'use strict'; return { restrict: 'E', scope: { map: &apo ...

The Angular service successfully provides a value, yet it fails to appear on the webpage

Currently, I am starting to dive into Angular from the ground up. One of my recent tasks involved creating a component called 'mylink' along with a corresponding service. In my attempt to retrieve a string value from the service using 'obse ...

What could be causing the lack of change in a dynamic input value in Angularjs?

There is an input with ng-model="articleTitle" and a div with {{articleTitle. When the input is typed in, the div is updated. However, there is a box that lists all articles enclosed by <div class="element">...</div>. When a list div is clicke ...

What is the best way to substitute </br> and <br/> with in a text?

Is there a way to replace </br> and <br/> with \n functionally? There seems to be varied responses to this query. Errors are often made when writing the break tag. The solutions for both types of breaks mentioned above are detailed below ...

The most effective method for displaying a timestamp in the user's specific timezone using Node.JS

My application logs user events and stores timestamps as dates in Mongo, which are then converted to JS Date objects with timezone information based on the server's timezone. Although I am using moment.js to format the dates, the issue arises because ...

When quickly typing, the input formatting using a computed property in Vue.js is not getting applied

Is there a way to format data in the following manner: m:ss, while restricting the input textbox to display only 3 characters or fewer? (m = minute, s = seconds) The code snippet below successfully formats the data in m:ss format. However, when entering m ...

How to access a variable in an Angular Factory's callback function from outside the factory

Here's a look at the structure of My Factory: .factory('MyFactory', function(){ return: { someFunction: functon(firstParam, secondParam, resultObject) { $http.get(url).success(resultObject); } ...

Utilizing Regex Patterns to Manipulate CSS Attributes

I am dealing with a string containing CSS properties and their values: str = "filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#000000'); background: -webkit-linear-gradient(top, black, wh ...

The appearance of the pop-up mask is displayed at lightning speed

Check out the demo here Here is the HTML code: <div class="x"> </div> <input class="clickMe" type="button" value="ClickMe"></input> This is the JS code: $(".clickMe").click( function() { ...

Collecting data from an HTML form filled out by users

I need a way to capture user input from an HTML form and display it later on my website. I want to show all the information users provide along with their pizza selections. I've been struggling for hours trying to make this work without success :( Spe ...

Effortlessly handle form submission with jQuery AJAX, automatically redirecting upon successful

I am working on a project using ASP.Net MVC where I have a view that submits form data to a controller action. In order to make this form submission more dynamic, I am trying to utilize jQuery to post the form via an AJAX call with the following code: $(" ...

In JavaScript, you can verify if a specific <input> element is an input-field

With the introduction of HTML5, a variety of new input types have been added: <input /> Is there a way to detect whether an input field is a text field (such as date, time, email, text, etc.) without explicitly specifying each type? I would like t ...

registering a back button action in Ionic2 for multiple pages

Currently, I am in the process of developing my Ionic2 app and have encountered a dilemma regarding the functionality of registerBackButtonAction. On one page, let's call it pageA, I have implemented this function and everything is functioning as exp ...

The custom error page in NextJS is failing to display

In my custom pages/404.ts file, I have coded the following: export default function NotFound() { return <h1>404 - Page Not Found</h1> } Additionally, there is another page that displays a 404 error when the organization is null: import Error ...

The persistent Bulma dropdown glitch that refuses to close

In the project I'm working on, I have implemented a Bulma dropdown. While the dropdown functions correctly, I am facing an issue when adding multiple dropdowns in different columns with backend integration. When one dropdown is open and another is cli ...

Choosing an SVG Circle Using TypeScript

I am facing an issue with selecting a simple SVG <circle> element in my DOM using TypeScript: <svg viewBox="0 0 200 200"> <circle cx="50" cy="50" r="45" id="myCircle"/> </svg> In ...

"Exploring the versatility of NextJS with dynamic route parameters

Can NextJS be configured to handle dynamic routes that match both /country and /country/city, while excluding matches like /country/city/whatever_content_here? The goal is to display the same content for either of the specified routes, regardless of whethe ...

CanJS utilizes mustache templates to escape HTML tags

I have a requirement to present a series of choices to the user. I am using a mustache template along with the CanJS JavaScript framework to showcase these options. The problem arises when attempting to display an option such as: Potato Rs. 12 The mustac ...

Leveraging grunt-develop

I have recently developed a basic NodeJS + Express application that runs smoothly when I use the command node app.js. However, my current task is to incorporate grunt-develop into my project. Here is how I configured it: grunt.initConfig({ develop: { ...