~
Extract nested attribute value from JSON String using Apex
Salesforce offers two main ways to extract values from a JSON string
JSON.deserialize()
This approach requires you to have a wrapper class/other valid entity to deserialize the data to.JSON.createParser(jsonString)
This approach requires you to loop through a bunch of confusing parser.nextToken() calls
In this article I am introducing an easy to use utility to extract inner attribute values from any JSON string. This is leveraging JSON.createParser()
. But once you have this utility, you don't have to go through the parser.nextToken()
confusion.
Example of use
Say you need to extract organization id from the following nested json string
{
"data": {
"user": {
"organization": {
"id": "123"
}
}
}
}
You can do this by simply passing the JSON string and the path of the parameter to the utility
Utils.extractAttributeFromJson('{"data":{"user":{"organization":{"id":"123"}}}}', 'data.user.organization.id');
Sample utility class
public with sharing class Utils {
/**************************************************************************************
* @Description This method extract value of inner attributes in a JSON
* @Param String - JSON string
* @Param String - JSON attribute path
* @Return String - This sample assumes returned value is a string
* @Example
* Utils.extractAttributeFromJson('{"data":{"user":{"organization":{"id":"123"}}}}', 'data.user.organization.id');
**************************************************************************************/
public static String extractAttributeFromJson(String jsonResponse, String attrString) {
if(String.isBlank(jsonResponse) || String.isBlank(attrString)) return null;
List<String> attrPath = attrString.split('\\.');
JSONParser parser = JSON.createParser(jsonResponse);
Integer index = 0;
parser.nextToken();
while(parser.nextToken() != null) {
if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
if(attrPath[index] == parser.getText()) {
if(index == attrPath.size()-1) {
parser.nextToken();
return parser.getText();
}else if(parser.nextToken() == JSONToken.START_OBJECT) {
index++;
}
}
}else if(parser.getCurrentToken() == JSONToken.START_OBJECT || parser.getCurrentToken() == JSONToken.START_ARRAY) {
parser.skipChildren();
}
}
return null;
}
}
Please note that it will be more performant to use JSON.createParser() directly if you have multiple attributes to extract from the JSON.