If you know the structure of the JSON before you get it then the easiest way is to create a class to define the Object.
For Example, given the following JSON String
{
"id" : "someID",
"street" : "someStreet",
"listOfClass" : [
{
"myVar" : "test"
}
]
"myArray" : ["1","2","3"]
}
Define the object as such:
public class myJSONClass{
public string id;
public string street;
public listOfClass[] listOfClass;
public String[] myArray;
public class listOfClasses{
public String myVar;
}
}
Do not think of it as a class to clutter your other classes, think of it as an object definition (what it is)
Then simply deserialize as follows:
myJSONClass obj = (myJSONClass)JSON.deserialize(JSONSTRING,myJSONClass.class);
Where it becomes tricky is when you are using reserved names or an unknown structure.
In most of those cases you need to use the JSON Parser methods to parse the string.The exception is if you only have a FEW reserved names you can replace them as such
JSONString = JSONString.replace('name','name_Z');
then define the property in the class as name_Z
. It will save a lot of work.
Back to your original point, if you have no class you can deserialize as such:
Map<String,Object> obj = JSON.deserializeUntyped(JSONString);
Then you can just cast everything to strings:
Map<String,String> results = New Map<String,String>();
for(String key : obj.keySet()){
results.put(key,string.valueOf(obj.get(key));
}
However in this case you lose the structure. For example, in your string if you have lists, arrays, etc, you get the string representation of the values and not the actual structure. More useful to define a class and work with it.
Note You do not have to have everything defined in the class to deserialize unless you use deserializeStrict. So if in my first example you removed public String id
it would still deserialize
In all the above examples, make sure to check for nulls and errors
Not a parser! Just deserialize:
public class Response { final Geometry geometry; }
public class Geometry { final Location location; }
public class Location { final Decimal latitude, longitude; }
Granted, your JSON payload is not valid as currently specified. The above would work though if your structure boils down to:
{
"geometry": {
"location": {
"latitude": 0.0,
"longitude": 0.0
}
},
"other_properties": { /*values*/ }
}
If you want to copy the payload format listed here, the class would be slightly different.
JSON
{
"results" : [
{
"address_components" : [...],
"formatted_address" : "1600 Amphitheatre Parkway, Mountain View, CA 94043, USA",
"geometry" : {
"location" : {
"lat" : 37.4224764,
"lng" : -122.0842499
},
"location_type" : "ROOFTOP",
"viewport" : {
"northeast" : {
"lat" : 37.4238253802915,
"lng" : -122.0829009197085
},
"southwest" : {
"lat" : 37.4211274197085,
"lng" : -122.0855988802915
}
}
},
"place_id" : "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"types" : [ "street_address" ]
}
],
"status" : "OK"
}
Apex
public class Response { final List<Result> results; }
public class Result { final Geometry geometry; }
public class Geometry { final Location location; }
public class Location { final Decimal latitude, longitude; }
Best Answer
You can convert JSON into equivalent Apex class like what @Shantanu has suggested, the only downside is sometimes we dont know the JSON structure to create Apex classes.
Instead, we can use
deserializeuntype
. deserializeuntype returns us the Map keyValue pair , which we can use on our advantage, and alter the value in map and again serialize it.Output =>
Source: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_System_Json.htm