JSON.deserializeUntyped parses raw JSON strings into flexible generic Apex maps (Map<String, Object>) or lists (List<Object>)—eliminating the need to define predefined wrapper classes for dynamic third-party API payloads.
In Salesforce development, working with JSON information is a common challenge when integrating with external systems or handling data in a flexible and dynamic way. Salesforce provides a powerful method called JSON.deserializeUntyped that allows developers to parse JSON strings into a manageable format. In this blog post, we'll explore the ins and outs of JSON.deserializeUntyped in Apex, understand its usage, and provide practical code examples to demonstrate its capabilities.
1. What is JSON.deserializeUntyped?
JSON.deserializeUntyped is an Apex method that allows you to parse JSON payloads into untyped data structures (maps and lists of generic Objects). Unlike typed deserialization—where you map JSON properties directly to specific Apex wrapper classes—untyped deserialization does not require defining a custom class beforehand. Instead, it provides a flexible way to parse and work with dynamic JSON structures on the fly.
2. Why Use JSON.deserializeUntyped?
There are scenarios where JSON payloads change frequently, contain dynamic keys, or are completely unknown at compile time. Using JSON.deserializeUntyped is particularly useful in these cases because it enables you to extract key values from varying JSON responses without writing or constantly updating rigid Apex wrapper classes.
3. Syntax and Parameters
The basic syntax of JSON.deserializeUntyped is as follows:
Object result = JSON.deserializeUntyped(jsonString);
Parameter: jsonString — The JSON-formatted string you want to parse and deserialize.
4. Code Examples
String jsonString = '{"name": "John", "age": 30, "isStudent": false}';
// Cast the deserialized object to a Map
Map<String, Object> jsonData = (Map<String, Object>) JSON.deserializeUntyped(jsonString);
String name = (String) jsonData.get('name');
Integer age = (Integer) jsonData.get('age');
Boolean isStudent = (Boolean) jsonData.get('isStudent');
String jsonString = '{"person": {"name": "Jane", "age": 25}}';
Map<String, Object> jsonData = (Map<String, Object>) JSON.deserializeUntyped(jsonString);
// Extract the nested object map
Map<String, Object> personData = (Map<String, Object>) jsonData.get('person');
String name = (String) personData.get('name');
Integer age = (Integer) personData.get('age');
String jsonString = '{"students": [{"name": "Alice", "age": 22}, {"name": "Bob", "age": 23}]}';
Map<String, Object> jsonData = (Map<String, Object>) JSON.deserializeUntyped(jsonString);
// Cast the array property to a List of Objects
List<Object> studentsData = (List<Object>) jsonData.get('students');
for (Object student : studentsData) {
Map<String, Object> studentData = (Map<String, Object>) student;
String name = (String) studentData.get('name');
Integer age = (Integer) studentData.get('age');
}
String jsonString = '{"name": "Invalid JSON}'; // Malformed JSON
try {
Map<String, Object> jsonData = (Map<String, Object>) JSON.deserializeUntyped(jsonString);
} catch (JSONException e) {
System.debug('Error parsing JSON: ' + e.getMessage());
}
- Validate JSON inputs or catch
JSONExceptionto prevent unexpected runtime failures. - Perform explicit type casting (
(String),(Integer),(Map<String, Object>)) when accessing untyped values. - Use
JSON.deserializeUntypedfor dynamic/unknown schemas; prefer typedJSON.deserializewith wrapper classes when API schemas are strict and well-defined.
Integer or Decimal. Direct type casting to an incorrect primitive type without checking or validating key existence can trigger a runtime System.TypeException or NullPointerException.
- Rule: Use
JSON.deserializeUntypedwhen JSON key structures vary; useJSON.deserialize(jsonString, ApexClass.class)when schemas are fixed. - Gain: Eliminates static class dependencies, reduces Apex metadata clutter, and easily parses changing payload schemas.
- Price: Requires explicit manual casting for every map key and list item in Apex logic.
- Limits: Deeply nested structures require multi-level type casting, increasing verbose null-checking requirements.
6. Conclusion
In this post, we explored the versatile JSON.deserializeUntyped method in Salesforce Apex. By removing the dependency on pre-defined Apex wrapper classes, untyped deserialization keeps your code dynamic, clean, and flexible when handling unpredictable JSON responses from third-party APIs.