Apex provides 3 classes for processing JSON:
- System.JSON – main methods here are serialize() and deserialize()
- System.JSONParser – provides methods for JSON parsing
- System.JSONGenerator – provides methods for JSON generation
System.JSON
System.JSON class provides methods for serialization and deserialization. For instance, the code snippet below serializes a list of Account objects into a JSON string:
1 2 | List<Account> accounts = [SELECT id, name FROM Account LIMIT 2]; String accountsJSON = JSON.serializePretty(accounts); //serializePretty indents the content for better readability |
Simply calling the serialize() method does the trick. The code above produces the following JSON output (depending on the data in your org the actual values may vary):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [ { "attributes" : { "type" : "Account", "url" : "/services/data/v24.0/sobjects/Account/001d000000Ard7uAAB" }, "Id" : "001d000000Ard7uAAB", "Name" : "United Oil & Gas, Singapore" }, { "attributes" : { "type" : "Account", "url" : "/services/data/v24.0/sobjects/Account/001d000000Ard7vAAB" }, "Id" : "001d000000Ard7vAAB", "Name" : "Edge Communications" } ] |
Deserialization of the accountsJSON string can easily be done using JSON.deserialize method:
1 | List<Account> accountsDeserialized = (List<Account>) JSON.deserialize(accountsJSON, List<Account>.class); |
Notice, however, that deserialization wouldn’t fully work with nested queries:
1 2 3 4 5 6 | List<Account> accounts = [SELECT id, name, (SELECT id, name FROM Contacts LIMIT 2) FROM Account LIMIT 2]; System.debug('Contacts' + accounts[0].contacts); //contacts are printed String accountsJSON = JSON.serializePretty(accounts); System.debug(accountsJSON); List<Account> accountsDeserialized = (List<Account>) JSON.deserialize(accountsJSON, List<Account>.class); System.debug('Contacts deserialized: '+ accountsDeserialized[0].contacts); //nothing gets printed |
The last debug statement doesn’t output any contacts.
Apex objects are handled similarly to the sObjets by the System.JSON class. For instance, the GoogleCalendar class from the upcoming demo application:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class GoogleCalendar { public String id; public String kind; public String etag; public String summary; public String description; public String location; public String timeZone; public String summaryOverride; public String colorId; public Boolean hidden; public Boolean selected; public String accessRole; public List defaultReminders; ... } |
is serialized and deserialized just like an sObject, except now you control the JSON structure through the Apex class:
1 2 3 4 | GoogleCalendar gCalendar = new GoogleCalendar(); //code to populate fields for the gCalendar is skipped String gCalJSON = JSON.serialize(gCalendar); GoogleCalendar gCalendarDeserialized = (GoogleCalendar) JSON.deserialize(gCalJSON, GoogleCalendar.class); |
Using the System.JSON class methods significantly reduces the number of script statements required to process JSON content and eliminates the need to dynamically inspect the object schema to figure out which fields exist. It is an ideal choice for scenarios that involve working with structured data such as Apex objects.
System.JSONGenerator
System.JSONGenerator class contains methods used to serialize Apex objects, and sObjects for that matter, into JSON content. The key difference between System.JSONGenerator and System.JSON’s serialize() method is that the former provides a “manual” control over the serialization process.
Below is a simple example that creates a basic JSON content after querying for contacts:
1 2 3 4 5 6 | List<Contact> contacts = [SELECT Id, Name FROM Contact LIMIT 10]; JSONGenerator generator = JSON.createGenerator(true); //instantiation of the generator generator.writeStartObject(); // Writes the starting marker of a JSON object '{' generator.writeNumberField('count', contacts.size()); //Writes the # of contacts generator.writeEndObject(); //Writes the ending marker of a JSON object '}' String jsonString = generator.getAsString(); |
The code above produces a simple JSON string analogous to the following:
1 2 3 | { "count" : 10 } |
Now let’s take a look at a more sophisticated example: serialization of a GoogleCalendarEvent Apex object used in the demo application. The structure of the JSON Google Events Resource is the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | { "id": string, "htmlLink": string, "created": datetime, "summary": string, "description": string, "location": string, "start": { "date": date, "dateTime": datetime, "timeZone": string }, "end": { "date": date, "dateTime": datetime, "timeZone": string }, "sequence": integer, "attendees": [ { "email": string, "displayName": string, "organizer": boolean, "self": boolean, "resource": boolean, "optional": boolean, "responseStatus": string, "comment": string, "additionalGuests": integer } ], "reminders": { "useDefault": boolean, "overrides": [ { "method": string, "minutes": integer } ] } } |
JSON structure above is mapped to the GoogleCalendarEvent class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class GoogleCalendarEvent { public String id; public String htmlLink; public DateTime created; public String summary; public String description; public String location; public Integer sequence; public GoogleEventTime start; public GoogleEventTime gEnd; public List attendees; public GoogleReminder reminders; ... } |
The calendar event JSON structure contains multiple data types, nested objects, and arrays – these are reflected in the GoogleCalendarEvent class and will require using various methods of the JSONGenerator class when creating the JSON content. In addition, some JSON structure’s properties, such as ‘end’, ‘date’, or ‘dateTime’ are reserved Apex keywords and hence had to be renamed, in this case into ‘gEnd’, ‘gDate’, and ‘gDateTime’ respectively for the GoogleCalendarEvent class.
For ease of understanding let’s walk through the serialization process in steps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //instantiate the generator JSONGenerator gen = JSON.createGenerator(true); gen.writeStartObject(); //this corresponds to an instance of the GoogleCalendarEvent class gen.writeStringField('summary', this.summary); gen.writeStringField('location', this.location); gen.writeFieldName('start'); gen.writeStartObject(); gen.writeObjectField('dateTime', this.start.gDatetime); gen.writeEndObject(); gen.writeFieldName('end'); gen.writeStartObject(); //for demo pusposes writeDateTimeField() is used instead of writeObjectField() gen.writeDateTimeField('dateTime', this.gEnd.gDatetime); gen.writeEndObject(); //serialize reminders gen.writeFieldName('reminders'); //writeObject() does the trick automatically since Apex object field names are the same as JSON field names gen.writeObject(this.reminders); ... |
The code above produces a JSON string analogous to the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | { “summary”: “summary_value”, “location”: “location_value”, "start": { "dateTime": "2012-02-15T18:03:32-08:00" }, "end": { "dateTime": "2012-02-15T19:03:32-08:00" }, "reminders": { "useDefault": false, "overrides": [ { "method": "email", "minutes": 1 }, { "method": "email", "minutes": 2 } ] } ... |
writeStringField() writes a text value while writeDateTimeField writes a dateTime.
Notice how writeObject() method serializes the whole reminders object including the overrides array, which is pretty handy. Let’s continue with the serialization of the array of event attendees:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ... gen.writeFieldName('attendees'); gen.writeStartArray(); //for each attendee create a JSON object for(GoogleEventAttendee gEventAttendee: this.attendees){ gen.writeStartObject(); gen.writeStringField('email', gEventAttendee.email); gen.writeBooleanField('optional', gEventAttendee.optional); gen.writeNumberField('additionalGuests', gEventAttendee.additionalGuests); gen.writeEndObject(); } gen.writeEndArray(); //end of the parent JSON object gen.writeEndObject(); String jsonString = gen.getAsString(); |
For demo purposes, instead of using the writeObject() method we “manually” constructed the attendees array which resulted in the following JSON structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 | ... "attendees": [ { "email": "testemail-1@test.com", "optional": true, "responseStatus": "needsAction" }, { "email": "testemail-0@test.com", "optional": true, "responseStatus": "needsAction" } ] |
System.JSONParser
In contrast to System.JSONGenerator, System.JSONParser does the opposite – it provides methods for parsing JSON content. Generally, JSONParser is useful for grabbing specific pieces of data without the need of a structure such as an Apex class.
For example, the code snippet below, taken from the authentication related code of the demo app, grabs access token and the expires_in parameter from the JSON response received from the authentication service:
1 2 3 4 5 6 7 8 9 10 11 12 13 | //resp is a JSON string JSONParser parser = JSON.createParser(resp); while (parser.nextToken() != null) { if ((parser.getCurrentToken() == JSONToken.FIELD_NAME)){ String fieldName = parser.getText(); parser.nextToken(); if(fieldName == 'access_token') { accesstoken = parser.getText(); } else if(fieldName == 'expires_in'){ expiresIn = parser.getIntegerValue(); } } } |
Depending on the JSON content you need to parse, it may make sense to break the while loop after all the necessary information has been obtained to prevent the unnecessary processing.
The System.JSONToken is an enumerator that provides values such as FIELD_NAME, START_OBJECT, END_OBJECT and others that inform you of the type of token currently being parsed.
Let’s now see how GoogleCalendarEvent object is constructed based on the parsed JSON string. For better readability let’s break down parsing code into several pieces:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //this – is an instance of GoogleCalendarEvent class //instantiate the parser JSONParser parser = JSON.createParser(jsonString); while (parser.nextToken() != null) { //if current token is a field name if (parser.getCurrentToken() == JSONToken.FIELD_NAME){ String fieldName = parser.getText(); System.debug('fieldName: ' + fieldName); //move to token after the field name parser.nextToken(); if(fieldName == 'id'){ this.id = parser.getText(); } else if(fieldName == 'htmlLink'){ this.htmlLink = parser.getText(); } ... |
The code above executes a while loop that walks through the whole JSON string using the parser.nextToken() method and parses simple field text values such as ‘id’ or ‘htmlLink’ using the parser.getText() method.
Let’s see how the ‘start’ object is parsed (code below is inside the while loop from the previous snippet):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ... else if(fieldName == 'start'){ //start is a GoogleEventTime object if(parser.getCurrentToken() == JSONToken.START_OBJECT){ while(parser.nextToken() != null){ if(parser.getCurrentToken() == JSONToken.FIELD_NAME){ if(parser.getText() == 'dateTime'){ parser.nextToken(); this.start.gDateTime = parser.getDateTimeValue(); break; } } } } } ... |
We use JSONToken.START_OBJECT enum to determine the beginning of the ‘start’ object, and then using the inner while loop iterate through its content to grab the this.start.gDateTime value using the parser.getDateTimeValue() method. Notice the break statement to stop the inner loop, without it the inner loop would continue processing the remaining JSON, which is the responsibility of the outer while loop.
Next, the ‘attendees’ array is parsed using the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ... else if(fieldName == 'attendees'){ if(parser.getCurrentToken() == JSONToken.START_ARRAY){ while(parser.nextToken() != null){ if(parser.getCurrentToken() == JSONToken.START_OBJECT){ //read GoogleEventAttendee object GoogleEventAttendee gEventAttendee = (GoogleEventAttendee) parser.readValueAs(GoogleEventAttendee.class); this.attendees.add(gEventAttendee); } else if(parser.getCurrentToken() == JSONToken.END_ARRAY){ break; } } } } ... |
After detecting the attendees array we use readValueAs() method to deserialize JSON structure into the GoogleEventAttendee object automatically, in other words without parsing the fields separately.
Demo App Walk-through
Prerequisites
- Download the unmanaged package into your developer org
- Go through the Google API configuration steps
- Authenticate with the API from using Google Apps custom object record
Step 1: Log In to a Developer Edition Org
Log in to a Developer Edition org. If you don’t have one, create a new one.
Step 2: Download the package to your Developer org
Step 3: Create a Google APIs Project
In the browser, navigate to the Google APIs Console, log in using a Google/Gmail account that you use to manage your calendar, and then create a project.
On the Services tab, turn on the Calendar API and accept Google’s terms of service.
Step 4: Enable the OAuth 2.0 Authentication for Your Google Calendar
On the API Access tab in the Google APIs Console, click Create an OAuth 2.0 client ID ….
Enter a Product Name such as GCalendar, then click Next.
On the next screen, click Web Application and enter c.your_salesforce_instance.visual.force.com/apex/GoogleLogin into the Your site or hostname field. Make sure you enter the correct Salesforce.com instance name, which can be obtained from the address bar of your browser:
As soon as you move the cursor focus out of the site or hostname field, the page updates so that the Redirect URI at the bottom of the dialog turns into https://c.your_salesforce_instance.visual.force.com/apex/GoogleLogin.
Finally, click Create client ID to generate the Client ID and Client Secret.
Step 5: Configure Authentication
Log in or return to your Developer Edition org and launch the JSON App from the Force.com App Menu at the top right corner.
Click the Google Apps tab, click New to create a new record, then populate the following fields:
- GoogleApp Name: enter GoogleApp
- Client ID: copy/paste the Client ID from the Google APIs Console
- Client Secret: copy/paste the Client Secret from the Google APIs Console
- Scope: enter https://www.googleapis.com/auth/calendar, which provides read-write access to Calendars, Calendar Events, and Calendar ACLs
Click Save.
Now that you have all the necessary information on the Google App record, you can authenticate against the Google APIs. First, disable Development Mode for your account, if necessary.
- Click Setup -> My Personal Information -> Personal Information -> Edit.
- Disable Development Mode, if necessary.
- Click Save.
To authenticate:
- Load the JSON App.
- Click Google Apps -> Google App -> Authenticate.
Google displays a page asking if you are OK with providing the required permissions to the application. Click Allow access to grant the access.
If everything went through fine, your GoogleApp record now has populated Access Token, Expires In, and Code fields. The access token typically is good for one hour.
Creating Calendars and Events
Assuming that the authentication went fine, now try creating a new Google calendar. Click the Create Calendar tab, enter some values for the calendar, and click Create Calendar.
When you press the Create Calendar button, a few actions take place:
- The information you entered gets assigned to a GoogleCalendar object.
- The object gets serialized into a JSON string using System.JSON.
- The JSON string gets passed to the Google Calendar API via an HTTP callout.
- The HTTP request header’s Content-Type property is set to application/json.
- As a result, Google creates a new calendar and sends back information such as id and etag as a JSON string.
- The app deserializes the JSON string into another GoogleCalendarObject and displays it in the Calendar Output section.
To verify the new calendar, navigate to your Gmail calendar. If everything went as expected, you should see a new calendar entry similar to the following:
Now, create a new event for the calendar you just created. To do so, click the Create Calendar Event tab, select the newly created calendar’s name from the drop-down, enter sample values and click Create Calendar Event:
A serialized (using JSONGenerator) GoogleCalendarEvent object gets passed to the API. Eventually, the Calendar Event Output section displays the deserialized (using JSONParser) GoogleCalendarEvent object obtained from the API call response. To verify if the calendar event got created, navigate to the Gmail calendar page.
Summary
The Apex JSON classes provide easy-to-use means of serializing/deserializing Apex objects into/from JSON content. Native JSON implementation empowers you with ability to build robust applications that integrate with third-party systems, various JavaScript libraries, or use HTML5.
Current Force.com API version: 24
Contact Us




























































