Guide on converting a JSON object into a TypeScript Object

I'm currently having issues converting my JSON Object into a TypeScript class with matching attributes. Can someone help me identify what I'm doing wrong?

Employee Class

export class Employee{
    firstname: string;
    lastname: string;
    birthdate: Date;
    maxWorkHours: number;
    department: string;
    permissions: string;
    typeOfEmployee: string;
    note: string;
    lastUpdate: Date;
}

Employee String

{
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": <anynumber>,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
    //I will add note later
}

My Attempt

let e: Employee = new Employee();

Object.assign(e, {
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
});

console.log(e);

Link to Typescript Playground

Answer №1

Using a TypeScript interface instead of a class can simplify things:

export interface Employee {
    typeOfEmployee_id: number;
    department_id: number;
    permissions_id: number;
    maxWorkHours: number;
    employee_id: number;
    firstname: string;
    lastname: string;
    username: string;
    birthdate: Date;
    lastUpdate: Date;
}

let jsonObj = JSON.parse(employeeString); // convert string to "any" object first
let employee = jsonObj as Employee;

However, if you prefer using a class, simple casting may not work as expected. For instance:

class Foo {
    name: string;
    public pump() { }
}

let jsonObj = JSON.parse('{ "name":"hello" }');
let fObj = jsonObj as Foo;
fObj.pump(); // throws an error, method is undefined!

When dealing with a class, you'll need to manually assign properties by writing a constructor that takes a JSON string/object and iterates through the properties like so:

class Foo {
    name: string;

    constructor(jsonStr: string) {
        let jsonObj = JSON.parse(jsonStr);
        for (let prop in jsonObj) {
            this[prop] = jsonObj[prop];
        }
    }
}

let fObj = new Foo(theJsonString);

Answer №2

The compiler allows you to cast the object returned from JSON.parse to a class because of TypeScript's structural subtyping principle, as explained in this documentation. This means that even though you don't have an instance of an actual Employee class, the object you receive has the same properties.

Here's a simpler example to illustrate this:

class A {
    constructor(public str: string, public num: number) {}
}

function logA(a: A) {
    console.log(`A instance with str: "${ a.str }" and num: ${ a.num }`);
}

let a1 = { str: "string", num: 0, boo: true };
let a2 = new A("stirng", 0);
logA(a1);
logA(a2);

(code in playground)

In this scenario, there are no errors because a1 satisfies type

A</code by having all the necessary properties. The <code>logA
function can be called without runtime errors, even if it receives an object that is not a direct instance of
A</code, as long as it contains the same properties.</p>

<p>However, when methods are introduced to classes, complications arise:</p>

<pre><code>class A {
    constructor(public str: string, public num: number) { }

    multiplyBy(x: number): number {
        return this.num * x;
    }
}

// This will not compile:
let a1 = { str: "string", num: 0, boo: true } as A;

// This will compile but lead to a runtime error:
let a2 = { str: "string", num: 0 } as A;

// Resulting in a runtime error:
a2.multiplyBy(4); // Error: Uncaught TypeError: a2.multiplyBy is not a function

(code in playground)


Edit

The following code snippet works perfectly:

const employeeString = '{"department":"<anystring>","typeOfEmployee":"<anystring>","firstname":"<anystring>","lastname":"<anystring>","birthdate":"<anydate>","maxWorkHours":0,"username":"<anystring>","permissions":"<anystring>","lastUpdate":"<anydate>"}';
let employee1 = JSON.parse(employeeString);
console.log(employee1);

(code in playground)

If you attempt to apply JSON.parse on an object instead of a string like in the following example:

let e = {
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
}
let employee2 = JSON.parse(e);

You will encounter an error because e is not a string but an object. If your data is already in object form, there is no need to utilize JSON.parse.

To create an instance of a class rather than just having an object with similar properties:

let e = new Employee();
Object.assign(e, {
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
});

Answer №3

const worker = <Worker>JSON.parse(employeeString);

It is important to note that strong typings are only enforced during compile time in JavaScript due to the lack of native support for it.

Answer №4

If your JSON data contains properties not present in your class, you can create a custom mapping to handle them.

export class Employee { ////
    static parse(json: string) {
           var data = JSON.parse(json);
            return new Employee(data.employeeType_id, data.firstName.. and more);
       }
}

You can also define a constructor within your Employee class for more precise mapping.

Answer №5

One of my favorite small libraries that I enjoy using is class-transformer.

This library has the capability to manage nested objects, convert strings into date objects, and handle different JSON property names efficiently.

If you haven't already, it may be worth checking out.

import { Type, plainToClass, Expose } from "class-transformer";
import 'reflect-metadata';

export class Employee {
    @Expose({ name: "uid" })
    id: number;

    firstname: string;
    lastname: string;
    birthdate: Date;
    maxWorkHours: number;
    department: string;

    @Type(() => Permission)
    permissions: Permission[] = [];
    typeOfEmployee: string;
    note: string;

    @Type(() => Date)
    lastUpdate: Date;
}

export class Permission {
    type: string;
}

let json: string = {
    "uid": 123,
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 1,
    "username": "<anystring>",
    "permissions": [
        {'type': 'read'},
        {'type': 'write'}
    ],
    "lastUpdate": "2020-05-08"
}

console.log(plainToClass(Employee, json));

Answer №6

To start, it is important to confirm that all attributes received from the service have matching names in your class. You can then parse the object and assign it to a new variable, as shown below:

const parsedData = JSON.parse(apiResponse);
const userObject: User = parsedData as User;

Give it a try!

Answer №7

Consider implementing the constructor method in your class.

Object.assign

is a crucial aspect.

Here is an example for your reference:

class Employee{
    firstname: string;
    lastname: string;
    birthdate: Date;
    maxWorkHours: number;
    department: string;
    permissions: string;
    typeOfEmployee: string;
    note: string;
    lastUpdate: Date;

    constructor(original: Object) { 
        Object.assign(this, original);
    }
}

let e = new Employee({
    "department": "<anystring>",
    "typeOfEmployee": "<anystring>",
    "firstname": "<anystring>",
    "lastname": "<anystring>",
    "birthdate": "<anydate>",
    "maxWorkHours": 3,
    "username": "<anystring>",
    "permissions": "<anystring>",
    "lastUpdate": "<anydate>"
});
console.log(e);

Answer №8

If you want to convert the JSON data into a specific class instance, you can follow these steps:

Assuming you have the following class structure:

export class Person{
    name: string= '';
}

and the JSON object:

let personObj = {
    "name": "Alice"
};

You can perform the conversion like this:

let p: Person = personObj as Person;

The result of console.log(p); will be:

{ name: 'Alice' }

Answer №9

One way to achieve this is by creating a new instance of your class and dynamically assigning its parameters from the JSON object.

const employeeData = JSON.parse(employeeString);
let emp:Employee=new Employee();
const keys=Object.keys(employeeData);
keys.forEach(key=>{
    emp[key]=employeeData[key];
});
console.log(emp);

At this point, 'emp' will be an object of type Employee that contains all the fields from the JSON object stored in 'employeeData'.

Answer №10

Is it possible to execute this task using the keyword "as" in the syntax?

async fetchContact(): Promise<Individual> {
      const accessUrl: string = this.baseApi;
    
      const result = await this.http.get(accessUrl).toPromise()
      return JSON.parse(result.json()) as Individual;
    }

Answer №11

Here is a streamlined approach that is effective for basic "flat" objects:

const updatedObjectList = originalObjectList.map(obj => Object.assign(new ObjectType(), obj));

After applying this transformation, you can easily utilize the methods associated with objects defined in the ObjectType class.

Answer №12

When the data is received from the server as an object, you can handle it in the following way:

The subscription to this.service with a parameter of 'data:any' allows for flexibility in data types and could potentially resolve any related issues.

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

There is an issue with the class relationship that is causing certain data to be missing from

I am looking to get this Json back into my project: { "data": { "id": 1, "username": "renato", "name": "Renato", "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2a4b594e4b594e6a455f5e4645454104494547 ...

Having trouble retrieving data from a JSON object in React/Redux?

It seems like there might be something obvious that I'm missing here - but I can't seem to figure out how to access the JSON data. I have a Container component: class About extends Component { componentDidMount(){ const APP_URL = 'htt ...

Firebase and Nx: Encountering issues with running emulators

I've been attempting to launch the Firebase emulators within the Nx workspace. Initially, I added firebase to my project: npm install firebase @angular/fire --save nx g @angular/fire:ng-add // configures the package in the project (unsuccessful) ng ...

Having difficulty in using pipe to filter records upon clicking the Button

I am having trouble filtering the records as needed. What I want is that when "All" is clicked, no filter should be applied. When any other option is clicked, the filter should be applied. HTML <div class="container " style="padding-top:100px"> ...

Let's explore further - delving into JSON & array manipulation using the foreach loop in Pure JavaScript

Although I have some experience with Java Script, I still consider myself a beginner in certain areas, particularly when it comes to accessing JSON objects and arrays. I've tried various syntax and options for accessing arrays using [], but so far, I ...

Converting nested arrays within a JSON object to a CSV format

I am currently utilizing the 'json-csv' library to convert a user's arrays with nested objects and arrays into a CSV format. var users = [ { subscriptions: [ { package : { name: &a ...

Sending the value of "username" between two components within Angular 2

I have a good understanding of nesting child components within parent components in Angular 2, but I'm a bit unclear on how to pass a single value from one component to another. In my scenario, I need to pass a username from a login component to a cha ...

How can elements be collapsed into an array using the Reactive approach?

Consider this TypeScript/Angular 2 code snippet: query(): Rx.Observable<any> { return Observable.create((o) => { var refinedPosts = new Array<RefinedPost>(); const observable = this.server.get('http://localhost/ra ...

Guide on toggling the button by clicking on the icon to turn it on or off

Within my angular application, I have implemented font icons alongside a toggle switch. Initially, the switch is in the ON state. The specific functionality desired is for clicking on an icon to change its color from white to red (this has been achieved) ...

POST requests in Angular Universal are making use of the IP address assigned to my server

My Angular Universal application (version 5.2.11) is currently hosted on Heroku, running on a Node server using express. I have implemented rate-limiters in all my POST routes to restrict requests by IP address, checking the request's IP through req.h ...

The or operator in Typescript does not function properly when used as a generic argument

My current configuration is as follows: const foo = async <T>(a): Promise<T> => { return await a // call server here } type A = { bar: 'bar' } | { baz: 'baz' } foo<A>({ bar: 'bar' }) .then(response =& ...

Guide to converting a log string into JSON using Javascript

I encountered a console log that appears as follows: 2021-01-06T09:06:05.541212726Z D saveGarment: Function execution took 736 ms, finished with status code: 204 2021-01-06T09:06:10.844901031Z D saveGarment: Function execution started 2021-01-06T09:06:16.1 ...

The typescript MenuProvider for react-native-popup-menu offers a range of IntrinsicAttributes

Looking to implement drop-down options within a Flatlist component, I've utilized the React Native Popup Menu and declared MenuProvider as the entry point in App.tsx. Encountering the following error: Error: Type '{ children: Element[]; }' ...

When integrating the @azure/msal-angular import into the Angular application, the screen unexpectedly goes blank,

Starting a new Angular app and everything is rendering as expected at localhost:4200 until the following change is made: @NgModule({ declarations: [ AppComponent, HeaderBannerComponent, MainContentComponent, FooterContentinfoComponent ...

`The validation in Angular 12 is successful, yet the mat-input remains invalid.`

Code snippet of Component- ngOnInit(): void { this.form = this.fb.group({ currentPassword: ['', [Validators.required], [this.matchCurrentPassword]], newPassword: ['', [Validators.required, Validators.minL ...

What is the process for including a library in a Java project that does not have JAR files?

Recently, I developed a Java project with the intention of incorporating a JSON library. After conducting some research on various JSON libraries available, I noticed that none of them provided JAR files as part of their package. Undeterred, I proceeded t ...

Guide to Setting Up Bootstrap 4 Beta Using Bower

Trying to update to the newest Bootstrap 4 Beta version via bower. Issue with this command: bower install bootstrap#v4.0.0-beta Getting the error message: no matches found: bootstrap#v4.0.0-beta Is there something incorrect in my process? This is how ...

How should one properly utilize string index with a BeautifulSoup object?

Attempting to scrape JSON data from an HTML webpage has presented a challenge for me. Despite using the find function to extract the JSON section, I encountered an error: Unsupported operand type(s) for -: 'NoneType' and 'int' This ...

Angular 2 and .NET Core 2.0 triggering an endless loop upon page refresh detection

My application, built with dotnet core 2.0 and angular 2, allows me to view member details. The process begins with a list page displaying all the members from a SQL Server database. Each member on the list has a link that leads to an individual details pa ...

I am experiencing issues with my JSON array when trying to integrate it into the Ionic framework with Cordova

I have successfully retrieved a JSON array from a URL in my Ionic app, but I am facing issues displaying it in a list. Here is the code snippet: home.ts file import { Component } from '@angular/core'; import { NavController } from 'ionic- ...