Parsing JSON response in LWC

Example 1: Parsing JSON from an Apex Controller

Apex Controller (ExampleController.cls)

public with sharing class ExampleController {
    @AuraEnabled(cacheable=true)
    public static String getJsonData() {
        return '{"name": "John Doe", "age": 30, "city": "San Francisco"}';
    }
}

LWC JavaScript (exampleComponent.js)

import { LightningElement, wire } from 'lwc';
import getJsonData from '@salesforce/apex/ExampleController.getJsonData';

export default class ExampleComponent extends LightningElement {
    jsonData;

    @wire(getJsonData)
    wiredJsonData({ error, data }) {
        if (data) {
            try {
                this.jsonData = JSON.parse(data); // Parse the JSON string
                console.log('Parsed JSON:', this.jsonData);
            } catch (e) {
                console.error('Error parsing JSON:', e);
            }
        } else if (error) {
            console.error('Error retrieving data:', error);
        }
    }
}

Example 2: Parsing JSON from a REST API Response

If you’re making a REST API call using fetch(), here’s how to handle the response:

fetch('https://api.example.com/data')
    .then(response => response.json()) // Parse JSON automatically
    .then(data => {
        console.log('Parsed JSON:', data);
    })
    .catch(error => console.error('Error fetching JSON:', error));

Example 3: Parsing Nested JSON

If the JSON response is nested, you can access the values like this:

Javascript

const response = `{
    "user": {
        "id": 101,
        "name": "Alice",
        "address": {
            "city": "New York",
            "zip": "10001"
        }
    }
}`;

const parsedData = JSON.parse(response);
console.log(parsedData.user.name); // Alice
console.log(parsedData.user.address.city); // New York

Best Practices

  1. Always wrap JSON.parse() in a try-catch block to handle potential errors.
  2. Ensure the response is a valid JSON string before parsing.
  3. Use optional chaining (?.) to avoid runtime errors on undefined properties.

Example 4: Looping Through JSON Data (Array of Objects)

Let’s say you receive the following JSON response from an Apex controller or REST API:

JSON

[
    {
        "id": 1,
        "name": "John Doe",
        "age": 30
    },
    {
        "id": 2,
        "name": "Jane Smith",
        "age": 28
    },
    {
        "id": 3,
        "name": "Alice Brown",
        "age": 35
    }
]

LWC JavaScript (exampleComponent.js)

import { LightningElement, wire } from 'lwc';
import getJsonData from '@salesforce/apex/ExampleController.getJsonData';

export default class ExampleComponent extends LightningElement {
    jsonData = [];

    @wire(getJsonData)
    wiredJsonData({ error, data }) {
        if (data) {
            try {
                this.jsonData = JSON.parse(data); // Parse the JSON array
                console.log('Parsed JSON:', this.jsonData);

                // Loop through the array using forEach
                this.jsonData.forEach(item => {
                    console.log(`ID: ${item.id}, Name: ${item.name}, Age: ${item.age}`);
                });

                // Using for...of loop
                for (let item of this.jsonData) {
                    console.log(`For Loop -> Name: ${item.name}, Age: ${item.age}`);
                }

            } catch (e) {
                console.error('Error parsing JSON:', e);
            }
        } else if (error) {
            console.error('Error retrieving data:', error);
        }
    }
}

Example 5: Looping Through Nested JSON

If your JSON structure has nested objects, such as:

JSON:

{
    "users": [
        { "id": 1, "name": "John Doe", "age": 30 },
        { "id": 2, "name": "Jane Smith", "age": 28 }
    ]
}

LWC JavaScript (exampleComponent.js)

const response = `{
    "users": [
        { "id": 1, "name": "John Doe", "age": 30 },
        { "id": 2, "name": "Jane Smith", "age": 28 }
    ]
}`;

const parsedData = JSON.parse(response);

// Loop through the "users" array
parsedData.users.forEach(user => {
    console.log(`User ID: ${user.id}, Name: ${user.name}, Age: ${user.age}`);
});

// Using for...of loop
for (let user of parsedData.users) {
    console.log(`For Loop -> Name: ${user.name}, Age: ${user.age}`);
}

Example 6: Display JSON Data in LWC HTML

You can also loop through JSON data in your LWC template using <template for:each>:

LWC HTML (exampleComponent.html)

<template for:each={jsonData} for:item="user">
    <p key={user.id}>{user.name} is {user.age} years old.</p>
</template>

Key Takeaways

  1. Use forEach() or for…of to loop through JSON arrays.
  2. For nested JSON, access child properties first (parsedData.users.forEach(…)).
  3. Use <template for:each> in LWC templates to display JSON data dynamically.

Example 7: Nested JSON data in an LWC lightning-datatable

Example Use Case

Let’s say you have this nested JSON response:

[
    {
        "id": 1,
        "name": "John Doe",
        "age": 30,
        "address": {
            "city": "New York",
            "state": "NY"
        }
    },
    {
        "id": 2,
        "name": "Jane Smith",
        "age": 28,
        "address": {
            "city": "Los Angeles",
            "state": "CA"
        }
    }
]

In this case, address is nested, and lightning-datatable doesn’t support directly displaying address.city or address.state. We will flatten the data before assigning it to the table.

LWC JavaScript (nestedDataTable.js)

import { LightningElement, wire, track } from 'lwc';
import getJsonData from '@salesforce/apex/ExampleController.getJsonData';

const COLUMNS = [
    { label: 'ID', fieldName: 'id', type: 'number' },
    { label: 'Name', fieldName: 'name', type: 'text' },
    { label: 'Age', fieldName: 'age', type: 'number' },
    { label: 'City', fieldName: 'city', type: 'text' },
    { label: 'State', fieldName: 'state', type: 'text' }
];

export default class NestedDataTable extends LightningElement {
    @track tableData = [];
    columns = COLUMNS;

    @wire(getJsonData)
    wiredJsonData({ error, data }) {
        if (data) {
            try {
                let parsedData = JSON.parse(data);

                // Flatten the nested JSON structure
                this.tableData = parsedData.map(item => ({
                    id: item.id,
                    name: item.name,
                    age: item.age,
                    city: item.address.city,  // Extract nested value
                    state: item.address.state // Extract nested value
                }));

                console.log('Flattened Data:', this.tableData);
            } catch (e) {
                console.error('Error parsing JSON:', e);
            }
        } else if (error) {
            console.error('Error retrieving data:', error);
        }
    }
}

LWC HTML (nestedDataTable.html)

<template>
    <lightning-card title="Nested JSON Data Table">
        <lightning-datatable
            key-field="id"
            data={tableData}
            columns={columns}
            hide-checkbox-column="true">
        </lightning-datatable>
    </lightning-card>
</template>

Explanation

1. Flattening the JSON

• We extract address.city and address.state and store them as separate fields in tableData.

2. Mapping Data to lightning-datatable

• columns define the fields to display.

• The parsed and flattened tableData is passed to lightning-datatable.

3. Displaying Data in LWC Template

• The lightning-datatable is used to show structured data.

Alternative: Using typeAttributes for Nested Data

If you don’t want to flatten the JSON, you can display nested data using typeAttributes. However, this works only for certain column types.

const COLUMNS = [
    { label: 'Name', fieldName: 'name', type: 'text' },
    { label: 'City', fieldName: 'address', type: 'text', typeAttributes: { fieldName: 'address.city' } }
];

This approach is limited and does not work for deeply nested structures.

Final Thoughts

  1. Flatten the data before assigning it to lightning-datatable.
  2. Use .map() to extract nested values (city, state).
  3. Use typeAttributes cautiously (only for simple cases).

Conclusion

Displaying nested JSON data in an LWC lightning-datatable requires flattening the structure before binding it to the component. Since lightning-datatable does not support direct access to nested properties, we use JavaScript’s .map() function to extract relevant fields.

By following this approach:

  1. Data remains structured and easy to manage.
  2. Lightning Data Table displays information properly without issues.
  3. Performance is optimized by working with a flat dataset.

For more complex use cases, such as displaying deeply nested objects or relationships, consider custom LWC components or nested tables inside a lightning-datatable.