https://developer.salesforce.com/page/Getting_Started_with_Apex_JSON
Introduction to JSON
According to http://www.json.org:
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. … JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others.
This definition, in short, highlights the key aspects of JSON: lightweight, human-readable, language-independent format, with parsers available in many languages.
JSON is becoming a de-facto standard for many APIs: for example, Twitter, Facebook, and Google APIs heavily rely on JSON. It is primarily used for serializing and transmitting structured data over a network connection, typically between a server and web application. In this realm JSON challenges XML. While there have been multiple debates on “JSON vs. XML” topic, it is agreed that JSON has the following key advantages over XML:
- JSON has a smaller footprint than XML, which means it can be transmitted and parsed faster than XML.
- JSON is simpler than XML because it has a smaller grammar and maps better to the data structures of the modern programming languages.
We should mention that XML has its advantages as well, such as XML schema for instance; however, a full comparison of XML vs. JSON is out of the scope of the current article.
Getting Started
Now that you have a general understanding of JSON, the following sections introduce you to the key Apex classes related to JSON.
System.JSON
The 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 |
List > accounts = [ SELECT id, name FROM Account LIMIT 2 ];
|
2 |
String accountsJSON = JSON.serializePretty(accounts); |
Simply calling the serialize() method does the trick. The code above produces the JSON output similar to the following:
04 |
"url" : "/services/data/v24.0/sobjects/Account/001d000000Ard7uAAB" |
06 |
"Id" : "001d000000Ard7uAAB" , |
07 |
"Name" : "United Oil & Gas, Singapore" |
11 |
"url" : "/services/data/v24.0/sobjects/Account/001d000000Ard7vAAB" |
13 |
"Id" : "001d000000Ard7vAAB" , |
14 |
"Name" : "Edge Communications" |
Deserialization of the accountsJSON string can easily be done using JSON.deserialize method:
1 |
List > accountsDeserialized = ( List > ) JSON.deserialize(accountsJSON, List > . class );
|
You can handle Apex objects similarly to sObjects with the System.JSON class. For instance, the GoogleCalendar class from the demo application you'll see a bit later ...
01 |
public class GoogleCalendar { |
05 |
public String summary; |
06 |
public String description; |
07 |
public String location; |
08 |
public String timeZone; |
09 |
public String summaryOverride; |
10 |
public String colorId; |
11 |
public Boolean hidden ; |
12 |
public Boolean selected; |
13 |
public String accessRole; |
14 |
public List > defaultReminders;
|
... is serialized and deserialized just like an sObject, except now you control the JSON structure through the Apex class:
1 |
GoogleCalendar gCalendar = new GoogleCalendar(); |
3 |
String gCalJSON = JSON.serialize(gCalendar); |
4 |
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 what fields exist. It is an ideal choice for scenarios that involve working with structured data such as Apex objects.
System.JSONGenerator
The System.JSONGenerator class contains methods used to serialize Apex objects, and sObjects for that matter, into JSON content using the standard JSON encoding. 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 basic JSON content after querying for contacts:
1 |
List > contacts = [ SELECT Id, Name FROM Contact LIMIT 10 ];
|
2 |
JSONGenerator generator = JSON.createGenerator( true ); |
3 |
generator.writeStartObject(); |
4 |
generator.writeNumberField( 'count' , contacts.size()); |
5 |
generator.writeEndObject(); |
6 |
String jsonString = generator.getAsString(); |
The code above produces a simple JSON string similar to the following:
Now take a look at a more sophisticated example: serialization of a GoogleCalendarEvent Apex object used in the upcoming demo application. The structure of the JSON Google Events Resource is the following:
06 |
"description" : string, |
22 |
"displayName" : string, |
27 |
"responseStatus" : string, |
29 |
"additionalGuests" : integer |
33 |
"useDefault" : boolean , |
The JSON structure above maps to the GoogleCalendarEvent class:
01 |
public class GoogleCalendarEvent { |
03 |
public String htmlLink; |
04 |
public DateTime created; |
05 |
public String summary; |
06 |
public String description; |
07 |
public String location; |
08 |
public Integer sequence; |
09 |
public GoogleEventTime start; |
10 |
public GoogleEventTime gEnd; |
11 |
public List > attendees;
|
12 |
public GoogleReminder reminders; |
The calendar event JSON structure contains multiple data types, nested objects, and arrays — the GoogleCalendarEvent class reflects these and requires the use of various methods of the JSONGenerator class when creating the JSON content. In addition, some JSON structure’s properties, such as end, date, and dateTime are reserved Apex keywords and hence were renamed to gEnd,gDate, and gDateTime, respectively, for the GoogleCalendarEvent class.
For clarity, here's a walk through of the serialization process in steps:
02 |
JSONGenerator gen = JSON.createGenerator( true ); |
03 |
gen.writeStartObject(); |
05 |
gen.writeStringField( 'summary' , this .summary); |
06 |
gen.writeStringField( 'location' , this .location); |
07 |
gen.writeFieldName( 'start' ); |
08 |
gen.writeStartObject(); |
09 |
gen.writeObjectField( 'dateTime' , this .start.gDatetime); |
11 |
gen.writeFieldName( 'end' ); |
12 |
gen.writeStartObject(); |
14 |
gen.writeDateTimeField( 'dateTime' , this .gEnd.gDatetime); |
17 |
gen.writeFieldName( 'reminders' ); |
19 |
gen.writeObject( this .reminders); |
The code above produces a JSON string analogous to the following:
02 |
“summary”: “summary_value”, |
03 |
“location”: “location_value”, |
05 |
"dateTime" : "2012-02-15T18:03:32-08:00" |
08 |
"dateTime" : "2012-02-15T19:03:32-08:00" |
writeStringField() writes a text value while writeDateTimeField() writes a dateTime. Notice how the writeObject() method serializes the entire reminders object including the overrides array — this is a handy tool that makes the code efficient. Now continue with the serialization of the array of event attendees:
02 |
gen.writeFieldName( 'attendees' ); |
03 |
gen.writeStartArray(); |
05 |
for (GoogleEventAttendee gEventAttendee: this .attendees){ |
06 |
gen.writeStartObject(); |
07 |
gen.writeStringField( 'email' , gEventAttendee.email); |
08 |
gen.writeBooleanField( 'optional' , gEventAttendee.optional); |
09 |
gen.writeNumberField( 'additionalGuests' , gEventAttendee.additionalGuests); |
15 |
String jsonString = gen.getAsString(); |
For demo purposes, instead of using the writeObject() method, the code manually constructs the attendees array, which results in the following JSON structure: