Creating a Typescript object from a JSON file

In my TypeScript app, I am utilizing API calls to retrieve objects. Specifically, I have a TypeScript User Object structured like this:

export class User {
    id : number;
    name : string;
    email : string;
}

Upon making the API call, the data returned looks like this:

{
    "id" : 3,
    "name" : "Jonn",
    "email" : "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b8d2d7d0d6f8ddc0d9d5c8d4dd96dbd7d5">[email protected]</a>"
}

I want to convert this JSON data into a User. Initially, I attempted this method:

let user : User = <User> myJson;

While I can successfully access properties of the user like user.name, the issue arises when trying to access methods within the User class. For example, if the User class contains a method such as:

getUppercaseName() : string {
    return this.name.toUpperCase();
}

The behavior observed is that while user.name returns John, attempting user.getUppercaseName() results in undefined.

What could be causing this discrepancy? And what would be the best approach to overcome this challenge?

Answer №1

Your approach involves treating classes as interfaces, which essentially means you are defining the structure without implementing it:

export interface User {
    id : number;
    name : string;
    email : string;
}

The reason why using classes in this manner doesn't raise any issues with the compiler is because:

TypeScript's type-checking principle revolves around the shape of values, a concept known as "duck typing" or "structural subtyping"

(learn more about duck typing)

This can be illustrated with an example:

class User {
    id: number;
    name: string;
    email: string;

    constructor(id: number, name: string, email: string) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
}

function logUser(user: User) {
    console.log(`user id: ${ user.id }, name: ${ user.name }, email: ${ user.email }`);
}

logUser({
    id: 1,
    name: "user 1",
    email: "mailaddress"
});

logUser(new User(2, "user 2", "anotheraddress"));

In both calls to logUser, objects that adhere to the interface of the User class are passed.

If you prefer working with instances of the class rather than object literals, you can do so like this:

new User(myJson.id, myJson.name, myJson.email);

You could also define an interface and implement it within the class for a similar effect:

interface IUser {
    id: number;
    name: string;
    email: string;
}

class User implements IUser {
    id: number;
    name: string;
    email: string;

    constructor(data: IUser) {
        this.id = data.id;
        this.name = data.name;
        this.email = data.email;
    }
}

...
new User(myJson);

Answer №2

Nitzan already went over the theory behind this concept, so I'll present an alternative strategy:

interface PersonalInfo {
   id: number;
   fullName: string;
   emailAddress: string;
}

class Person {
   personalInfo: PersonalInfo;
   constructor(personalInfo: PersonalInfo) {
       this.personalInfo = personalInfo;
   }
   displayFullNameInUpperCase(): string {
       return this.personalInfo.fullName.toLocaleUpperCase();
   }
}

const userData = {
   id: 4,
   fullName: "Alice Doe",
   emailAddress: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="46757171677a737c6e7773777b">[email protected]</a>"
}

let individual: Person = new Person(userData);

Answer №3

When dealing with a User object that has 50 or more properties, there can be some challenges...

To address this issue, consider adding a constructor to your User object that extends your JSON object.

export class User {
    constructor( jsonData: any )
    {
      $.extend(this, jsonData);
    }
    id : number;
    name : string;
    email : string;
    getUpperCaseName() {...}
}

When making an ajax callback, you can create a new User object from the received JSON data:

let newUser = new User( jsonUserData );
let userName = newUser.getUpperCaseName();

For a detailed explanation of this solution, check out this helpful post.

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

Transform the data attributes into a list without any specific order

Can someone help me with this code snippet? <a href="#" data-teste='["apresentacoes/1.jpg", "apresentacoes/2.jpg", "apresentacoes/3.jpg"]'> <img src="apresentacoes/thumbs/1.jpg" alt="img01"/> </a> I would like to modify th ...

Issue with Django and Angular 4 - The requested resource is missing the 'Access-Control-Allow-Origin' header

This is my django code snippet Whenever I test my delete function, this error occurs: The requested resource does not include the 'Access-Control-Allow-Origin' header. This means that the origin is not permitted access. The response resulted ...

Storing data asynchronously in Angular 4

In the process of developing a testing application, I have integrated Firebase to host thousands of questions. In order to avoid redundant downloads of questions, I have set up a question service that retrieves the questions in the constructor: this.db.li ...

Inquiring about a particular key-value in a buffer variable in GoLang

Within my code, I have a variable buffer that holds a collection of key-value pairs in an array format like this: [{"Key":"area1", "Record": {"name":"belfast","type":"surburban","v ...

changing quot to &quot within the MVC framework

Here is a sample code snippet: <script> $('#data').jstree({ 'core': { 'data': [@:{"text" : "ABC"}, @subtree();]}}) @function { public string subtree(){ return "{&bsol ...

Is there a way to convert an Xml raw string into Xml or Json Output Format?

I am attempting to use FormatFilter in order to generate 'json' or 'xml' output from a controller response. The issue is that my initial xml string is randomly generated. I am working with DotNet Core 2.2 and here is the current code ...

Tips for guaranteeing the shortest possible period of operation

I am in the process of constructing a dynamic Angular Material mat-tree using data that is generated dynamically (similar to the example provided here). Once a user expands a node, a progress bar appears while the list of child nodes is fetched from the ...

Loading JSON Data into Table

I have retrieved JSON data from an API and now I want to display it in a table. To achieve this, I created a global array where I store the JSON data before populating the table with it. do { let json = try JSONSerialization.jsonObject(with: data!, op ...

What could be the cause of this malfunction in the Angular Service?

After creating an Angular app with a controller, I noticed that while I can successfully interact with the controller using Postman (as shown in the screenshot below), I faced issues with displaying data at the frontend. I implemented a new component alon ...

Setting up Zurb Foundation in a VueJS TypeScript project: Step-by-step guide

I'm currently facing a challenge involving the integration of Zurb Foundation v6.5.3 into a VueJS project that is TypeScript-based and was created using @Vue/CLI. The project already includes jQuery type definitions. In the code snippet below, you can ...

Subscription Code Incrementally Triggering Upon Each Component Load

Within the initialization of my component, I have the following code: public Subscription: Subscription; ngOnInit() { this.subscription = this.myService.currentData.subscribe( dataReceived => { this.data = dataReceived; this.useDa ...

Query: Is there a way to search for a key that is a numerical string saved in a variable in jq?

Let me start by saying sorry if this question has been raised before, although I do not believe it has. I am dealing with a json-string that is the result of a cURL command in a bash script. Here's an example of what it looks like: {"123456" ...

Error in versionName for Nativescript 7 or later

Nativescript version: 8.3; vue/ts. I'm facing an issue with assigning versioning to my Nativescript application. Despite following the guidelines, the versionName remains 1.0.0 and versionCode stays at 1. This problem persists whether I am debugging ...

Issue with service being undefined upon refreshing an Angular 9 application that includes a resolver in its routing logic

Having a Component that loads user data and needs to handle direct access via URL, I implemented a resolver service in the router. It works fine when accessing the component through routing within the application. But upon refreshing the page with the URL, ...

Performing a MySQL query that utilizes JSON data objects

Wondering why there are no results showing up even though the query seems correct. I added a WHERE clause and now it's not working, but previously it was... $query="select distinct c.id, c.FirstName, c.LastName, c.EmailAddress, c.MemberStatus from d ...

Javascript - Implement validation pattern requiring a minimum of one character that is not a space

I am looking to create an input field with a validation pattern that does not allow spaces. While I found a solution that includes a pattern for alphanumeric characters and spaces, it does not account for special characters such as č, ć, ž, đ, š, and ...

Using CodeIgniter's AJAX and JSON functionality, dynamically change the color of a div based on the

Can someone help me with an ajax beginner question? I have a table in my database called companies with columns: id, company_name, select_button, status Whenever a user clicks the select_button on a company row, the status changes to 2 without any issues ...

What properties are missing from Three.js Object3D - isMesh, Material, and Geometry?

Currently, I am working with three.js version r97 and Angular 7. While I can successfully run and serve the application locally, I encounter type errors when attempting to build for production. Error TS2339: Property 'isMesh' does not exist on ...

Angular 4 Form remains valid even when an incorrect value is entered

Within my Angular 4 project, I encounter the issue of controlling input fields in multiple forms. Specifically, I need a mechanism to disable the save button if the input value is incorrect. For example, when I require an input field to only accept positi ...

Enhanced support for Vuex store in Visual Studio Code

I am currently developing an application using Vue.js 2, Vuex, and TypeScript within Visual Studio Code. I have the Vetur extension installed to enhance my development experience. While I have managed to set up intellisense for most of my project with a ...