React Js json response to Typescript object

Last updated : Jul 30, 2023 12:00 AM

React Js uses API calls to retrieve data for its components. The API calls usually return JSON data. If I use Typescript in my React Js application, I must cast the JSON response to a compatible Typescript interface to access the JSON response data. Let's see how to achieve that.

JSON response object

I will use the below JSON response to design my interface. It covers most of the scenarios we encounter in JSON responses.

JSON fileDescription
{
  "contactDetails": {
    "firstName": "Micky",
    "lastName": "Mouse",
    "email": "mm@disneyland.com",
    "address": {
      "street": "Some street",
      "city": "Anaheim",
      "state": "CA",
      "zip": "9280"
    },
    "phone": [{
      "number": "1800-Disney",
      "type": "home"
    },
    {
      "number": "1800-Disney",
      "type": "cell"
    }
    ]
  },
  "workDetails": {
    "companyName": "LearnBestCoding",
    "address": {
      "street": "Some street",
      "city": "Edmond",
      "state": "OK",
      "zip": "73034"
    },
    "phone": {
      "number": "1800-work",
      "type": "direct"
    }
  },
  "experience": {
    "releventExperience": "10 years",
    "company": [{
      "name": "Company 1",
      "position": "Research Scientist",
      "fromTo": "2022 - Present"
    }, {
      "name": "Company 2",
      "position": "Research Assistant",
      "fromTo": "2012 - 2021"
    }, {
      "name": "Company 3",
      "position": "Architect",
      "fromTo": "2011 - 2012"
    }]
  },
  "education": {
    "institutions": [{
      "name": "UCO",
      "certification": "BSc Computer Science"
    }, {
      "name": "UCLA",
      "certification": "MSc Computer Science"
    }]
  }
}

Design interface to match JSON response

I can break down my JSON response into four main objects.

{
  contactDetails: {},
  workDetails: {},
  experience: {},
  education: {}
}

Now let's take a look at the contactDetails object. It has an address object and an array of phone numbers.

contactDetails: {
   address: {},
   phone: []
}

Now I have built a skeleton for the contactDetails object. Let's fill in the rest of the properties to complete the contactDetails.

contactDetails: {
   firstName: string
   lastName: string
   email: string
   address: {
      street: string
      city: string
      state: string
      zip: string
   },
   phone: {
      type: string
      number: string
   }[]
}

The workDetails object also contains the address and phone objects.

workDetails: {
   companyName: string
   address: {
      street: string
      city: string
      state: string
      zip: string
   },
   phone: {
      type: string
      number: string
   }
}

The experience and education objects can be composed like the below.

experience: {
   releventExperience: string
   company: {
      name: string
      position: string
      fromTo: string
   }[]
}
education: {
   institutions: {
      name: string
      certification: string
   }[]
}

The address and phone objects are common for contactDetails and workDetails objects. Therefore, bringing those two into two separate interfaces is a good practice.

interface Address {
   street: string
   city: string
   state: string
   zip: string
}

interface Phone {
   type: string
   number: string
}

With that change, my contactDetails and workDetails objects look like the below.

contactDetails: {
   firstName: string
   lastName: string
   email: string
   address: Address,
   phone: Phone[]
}
workDetails: {
   companyName: string
   address: Address,
   phone: Phone
}

Next, I must pick a meaningful name for the entire object. The interface name Candidate sounds like a good candidate. Here is the complete code example of what I have explained here. For the sake of simplicity, I don't call an API. Instead, I use a hard-coded JSON. So I can contain the entire example into a single file.

import styles from './Table.module.css'

const json = {
   "contactDetails": {
      "firstName": "Micky",
      "lastName": "Mouse",
      "email": "mm@disneyland.com",
      "address": {
         "street": "Some street",
         "city": "Anaheim",
         "state": "CA",
         "zip": "9280"
      },
      "phone": [{
         "number": "1800-Disney",
         "type": "home"
      },
      {
         "number": "1800-Disney",
         "type": "cell"
      }
      ]
   },
   "workDetails": {
      "companyName": "LearnBestCoding",
      "address": {
         "street": "Some street",
         "city": "Edmond",
         "state": "OK",
         "zip": "73034"
      },
      "phone": {
         "number": "1800-work",
         "type": "direct"
      }
   },
   "experience": {
      "releventExperience": "10 years",
      "company": [{
         "name": "Company 1",
         "position": "Research Scientist",
         "fromTo": "2022 - Present"
      }, {
      "name": "Company 2",
         "position": "Research Assistant",
         "fromTo": "2012 - 2021"
      }, {
         "name": "Company 3",
         "position": "Architect",
         "fromTo": "2011 - 2012"
      }]
   },
   "education": {
      "institutions": [{
         "name": "UCO",
         "certification": "BSc Computer Science"
      }, {
         "name": "UCLA",
         "certification": "MSc Computer Science"
      }]
   }
}

interface Address {
   street: string
   city: string
   state: string
   zip: string
}

interface Phone {
   type: string
   number: string
}

interface Candidate {
   contactDetails: {
      firstName: string
      lastName: string
      email: string
      address: Address,
      phone: Phone[]
   }
   workDetails: {
      companyName: string
      address: Address,
      phone: Phone
   }
   experience: {
      releventExperience: string
      company: {
         name: string
         position: string
         fromTo: string
      }[]
   }
   education: {
      institutions: {
      name: string
      certification: string
      }[]
   }
}

const response: Candidate = json

const App = () => {
  return <table className={styles.customers}>
    <tr><td>First Name</td><td>{response.contactDetails.firstName}</td></tr>
    <tr><td>Last Name</td><td>{response.contactDetails.lastName}</td></tr>
    <tr><td>Email</td><td>{response.contactDetails.email}</td></tr>
    <tr>
      <td>Address</td>
      <td>
        {response.contactDetails.address.street}<br/>
        {response.contactDetails.address.city}<br/>
        {response.contactDetails.address.state}<br/>
        {response.contactDetails.address.zip}
      </td>
    </tr>
    <tr>
      <td>Phone</td>
      <td>{response.contactDetails.phone.map((phone) => {
        return <>{`${phone.type} ${phone.number}`}<br/></>
      })}</td>
    </tr>
    <tr><td>Company</td><td>{response.workDetails.companyName}</td></tr>
    <tr>
      <td>Address</td>
      <td>
        {response.workDetails.address.street}<br/>
        {response.workDetails.address.city}<br/>
        {response.workDetails.address.state}<br/>
        {response.workDetails.address.zip}
      </td>
    </tr>
    <tr>
      <td>Phone</td>
      <td>{`${response.workDetails.phone.type} ${response.workDetails.phone.number}`}</td>
    </tr>
    <tr><td>Experience</td><td>{response.experience.releventExperience}</td></tr>
    <tr>
      <td>Companies</td>
      <td>{response.experience.company.map((exp) => {
        return <>{`${exp.name} ${exp.position} ${exp.fromTo}`}<br/></>
      })}</td>
    </tr>
    <tr>
      <td>Education</td>
      <td>{response.education.institutions.map((institute) => {
        return <>{`${institute.name} ${institute.certification}`}<br/></>
      })}</td>
    </tr>
  </table>
}
export default App;
Lance

By: Lance

Hi, I'm Lance Raney, a dedicated Fullstack Developer based in Oklahoma with over 15 years of exp

Read more...