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

Show categories that consist solely of images

I created a photo gallery with different categories. My goal is to only show the categories that have photos in them. Within my three categories - "new", "old", and "try" - only new and old actually contain images. The issue I'm facing is that all t ...

What could be causing the JSON.parse() function to fail in my program?

Currently utilizing Django and attempting to fetch data directly using javascript. Below are the code snippets. Within the idx_map.html, the JS section appears as follows: var act = '{{ activities_json }}'; document.getElementById("json") ...

Choosing everything with ngrx/entity results in not selecting anything

Issue with Selector I am facing an issue with my selector in the component. Despite making the call, the component does not update with books from the FakeApiService. The actions and effects seem to be functioning correctly. The problem seems to be relat ...

Building an Event Scheduler in Outlook Calendar with Angular 5

Currently, I am utilizing Angular version 5.2 for a room booking portal project. One of the requirements entails adding an event to the Outlook calendar on the day a room is booked. The system includes a table listing all bookings, with a button in each ro ...

When using both @RestController and @GetMapping, the simple Hello World List does not return a JSON array

Having trouble getting a JSON response with @RestController and @GetMapping in my Spring Boot application. The code runs on localhost, but the output is not in JSON format. Can someone help me fix this issue? @SpringBootApplication @RestController public c ...

When receiveMessage is triggered, the FCM push notification fails to refresh the view

After following this helpful tutorial on Push Notifications with Angular 6 + Firebase Cloud Messaging, everything is working perfectly. I am able to receive notifications when using another browser. To ensure that my notification list and the length of no ...

Retrieve dynamic JSON data in a NodeJS RESTful API through fetching

Currently, I am in the process of retrieving JSON data from an API using node-fetch within my Express application. So far, I have been successful in fetching data by entering the absolute URL. However, my goal is to fetch data that is entered in req.body l ...

Tips for sharing JSON data between JavaScript files

Here is the initial script setup to utilize static .json files for displaying and animating specific content. The code provided is as follows: var self = this; $.getJSON('data/post_'+ index +'.json', function(d){ self.postCa ...

This property cannot be found on the specified type

So, I have this TypeScript function that will return one of two different objects based on the input value: function myfunc(isError:boolean): {response:string}|{error:string} { if(isError) return {error:''} return {response:''} } N ...

Sending binary information from a .net core web api to a typescript application

I currently have a .net core 3.0 web api application connected to an angular 8 client. While I have successfully transferred data between them using json serialization, I am now looking for a way to transfer a bytes array from the api to the client. After ...

Ways to delete a blank key from a MySQL json field

I need to modify a MySQL table with a json field that contains an empty key. I am looking for a way to remove this empty key from the JSON field. Current data: update t1 set info = REPLACE(info, '"": "",', ''); The ...

What is the process for selectively adding interceptors to app.module?

After searching through various topics, I have not found a solution that addresses my specific issue. To provide some context, we have an Angular App that operates in two modes - one mode uses one API while the other mode utilizes a different API. My goal ...

Utilizing Base64 encoding and JSON for transferring high-resolution images

I have been utilizing this function to transmit an image to a server through JSON. To achieve this, I start by converting the image into NSData, then into NSString using Base64. The process works smoothly with smaller images, however, it crashes when attem ...

An issue occurred while attempting to retrieve information from the database table

'// Encounter: Unable to retrieve data from the table. // My Code const sql = require('mssql/msnodesqlv8'); const poolPromise = new sql.ConnectionPool({ driver: 'msnodesqlv8', server: "test.database.windows.net", ...

Establishing a response header in conjunction with a specified string

I'm facing an issue while attempting to include a token in the headers of an HTTP request from backend to frontend, along with sending a custom string. Despite my efforts, I am encountering a problem where the token appears as null on the client-side. ...

The method window.getComputedStyle retrieves the CSS max-height property containing an unresolved calc() function

Has anyone encountered a challenge with a function related to Angular in their project? Here is a snippet of the code causing issues: console.log(window.getComputedStyle(this.frontLayer.nativeElement).maxHeight); And within the component template: <di ...

Tips for clearing out text in a <p> tag with javascript when it exceeds a specific length of 100 characters

Is there a way to automatically truncate text to (...) when it exceeds 100 characters inside a paragraph with the class .class? For instance, if I have a long paragraph like this: <div class='classname'> <p>Lorem ipsum dolor sit ame ...

Unable to associate ngModel because it is not recognized as a valid property of the "Component"

Currently, I am in the process of creating a custom form component using Angular 4. I have included all necessary components for ngModel to function properly, but unfortunately, it is not working as expected. Below is an example of my child component: ex ...

Leveraging .tsx components within nested .tsx components in React Native

Currently, I am delving into the world of building apps using TypeScript in React Native. Coming from a background as a Swift developer, adjusting to JavaScript and TypeScript has been an interesting journey. An observation that stood out to me is the cha ...

Is it possible to merge rows feature in Java programming?

I am encountering a problem where my attempt to merge rows is resulting in three separate objects instead of a single object that matches the desired schema. ...