Getting Started with Apex JSON
来源:互联网 发布:演唱会购票软件 编辑:程序博客网 时间:2024/05/15 01:02
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
<Account
>
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:
01
{
02
"attributes"
: {
03
"type"
:
"Account"
,
04
"url"
:
"/services/data/v24.0/sobjects/Account/001d000000Ard7uAAB"
05
},
06
"Id"
:
"001d000000Ard7uAAB"
,
07
"Name"
:
"United Oil & Gas, Singapore"
08
}, {
09
"attributes"
: {
10
"type"
:
"Account"
,
11
"url"
:
"/services/data/v24.0/sobjects/Account/001d000000Ard7vAAB"
12
},
13
"Id"
:
"001d000000Ard7vAAB"
,
14
"Name"
:
"Edge Communications"
15
}
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
);
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 {
02
public
String
id;
03
public
String
kind;
04
public
String
etag;
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
<GoogleReminderOverride
>
defaultReminders;
15
...
16
}
... is serialized and deserialized just like an sObject, except now you control the JSON structure through the Apex class:
1
GoogleCalendar gCalendar
=
new
GoogleCalendar();
2
//code to populate fields for the gCalendar is skipped
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
<Contact
>
contacts
=
[
SELECT
Id, Name
FROM
Contact LIMIT
10
];
2
JSONGenerator generator
=
JSON.createGenerator(
true
);
//instantiation of the generator
3
generator.writeStartObject();
// Writes the starting marker of a JSON object '{'
4
generator.writeNumberField(
'count'
, contacts.size());
//Writes the # of contacts
5
generator.writeEndObject();
//Writes the ending marker of a JSON object '}'
6
String
jsonString
=
generator.getAsString();
The code above produces a simple JSON string similar to the following:
1
{
2
"count"
:
10
3
}
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:
01
{
02
"id"
: string,
03
"htmlLink"
: string,
04
"created"
: datetime,
05
"summary"
: string,
06
"description"
: string,
07
"location"
: string,
08
"start"
: {
09
"date"
: date,
10
"dateTime"
: datetime,
11
"timeZone"
: string
12
},
13
"end"
: {
14
"date"
: date,
15
"dateTime"
: datetime,
16
"timeZone"
: string
17
},
18
"sequence"
: integer,
19
"attendees"
: [
20
{
21
"email"
: string,
22
"displayName"
: string,
23
"organizer"
:
boolean
,
24
"self"
:
boolean
,
25
"resource"
:
boolean
,
26
"optional"
:
boolean
,
27
"responseStatus"
: string,
28
"comment"
: string,
29
"additionalGuests"
: integer
30
}
31
],
32
"reminders"
: {
33
"useDefault"
:
boolean
,
34
"overrides"
: [
35
{
36
"method"
: string,
37
"minutes"
: integer
38
}
39
]
40
}
41
}
The JSON structure above maps to the GoogleCalendarEvent class:
01
public
class
GoogleCalendarEvent {
02
public
String
id;
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
<GoogleEventAttendee
>
attendees;
12
public
GoogleReminder reminders;
13
...
14
}
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:
01
//instantiate the generator
02
JSONGenerator gen
=
JSON.createGenerator(
true
);
03
gen.writeStartObject();
04
//this corresponds to an instance of the GoogleCalendarEvent class
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);
10
gen.writeEndObject();
11
gen.writeFieldName(
'end'
);
12
gen.writeStartObject();
13
//for demo pusposes writeDateTimeField() is used instead of writeObjectField()
14
gen.writeDateTimeField(
'dateTime'
,
this
.gEnd.gDatetime);
15
gen.writeEndObject();
16
//serialize reminders
17
gen.writeFieldName(
'reminders'
);
18
//writeObject() does the trick automatically since Apex object field names are the same as JSON field names
19
gen.writeObject(
this
.reminders);
20
...
The code above produces a JSON string analogous to the following:
01
{
02
“summary”: “summary_value”,
03
“location”: “location_value”,
04
"start"
: {
05
"dateTime"
:
"2012-02-15T18:03:32-08:00"
06
},
07
"end"
: {
08
"dateTime"
:
"2012-02-15T19:03:32-08:00"
09
},
10
"reminders"
: {
11
"useDefault"
:
false
,
12
"overrides"
: [
13
{
14
"method"
:
"email"
,
15
"minutes"
:
1
16
},
17
{
18
"method"
:
"email"
,
19
"minutes"
:
2
20
}
21
]
22
}
23
...
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:
01
...
02
gen.writeFieldName(
'attendees'
);
03
gen.writeStartArray();
04
//for each attendee create a JSON object
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);
10
gen.writeEndObject();
11
}
12
gen.writeEndArray();
13
//end of the parent JSON object
14
gen.writeEndObject();
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:
01
...
02
"attendees"
: [
03
{
04
"email"
:
"testemail-1@test.com"
,
05
"optional"
:
true
,
06
"responseStatus"
:
"needsAction"
07
},
08
{
09
"email"
:
"testemail-0@test.com"
,
10
"optional"
:
true
,
11
"responseStatus"
:
"needsAction"
12
}
13
]
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 theexpires_in parameter from the JSON response received from the authentication service:
01
//resp is a JSON string
02
JSONParser parser
=
JSON.createParser(resp);
03
while
(parser.nextToken() !=
null
) {
04
if
((parser.getCurrentToken()
=
= JSONToken.FIELD_NAME)){
05
String
fieldName
=
parser.getText();
06
parser.nextToken();
07
if
(fieldName
=
=
'access_token'
) {
08
accesstoken
=
parser.getText();
09
}
else
if
(fieldName
=
=
'expires_in'
){
10
expiresIn
=
parser.getIntegerValue();
11
}
12
}
13
}
Depending on the JSON content you need to parse, it may make sense to break the while loop after your code obtains all the necessary information and thus avoid 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. Now take a look at how to construct the GoogleCalendarEvent object based on a parsed JSON string. For better readability, we'll break down parsing code into several pieces:
01
//this – is an instance of GoogleCalendarEvent class
02
//instantiate the parser
03
JSONParser parser
=
JSON.createParser(jsonString);
04
while
(parser.nextToken() !=
null
) {
05
//if current token is a field name
06
if
(parser.getCurrentToken()
=
= JSONToken.FIELD_NAME){
07
String
fieldName
=
parser.getText();
08
System
.debug(
'fieldName: '
+ fieldName);
09
//move to token after the field name
10
parser.nextToken();
11
if
(fieldName
=
=
'id'
){
12
this
.id
=
parser.getText();
13
}
14
else
if
(fieldName
=
=
'htmlLink'
){
15
this
.htmlLink
=
parser.getText();
16
}
17
...
The code above executes a while loop that walks through the entire JSON string using the parser.nextToken() method and parses simple field text values such as id or htmlLink using the parser.getText() method. Now take a look at how to parse the start object (the code below is inside the while loop from the previous snippet):
01
...
02
else
if
(fieldName
=
=
'start'
){
//start is a GoogleEventTime object
03
if
(parser.getCurrentToken()
=
= JSONToken.START_OBJECT){
04
while
(parser.nextToken() !=
null
){
05
if
(parser.getCurrentToken()
=
= JSONToken.FIELD_NAME){
06
if
(parser.getText()
=
=
'dateTime'
){
07
parser.nextToken();
08
this
.start.gDateTime
=
parser.getDateTimeValue();
09
break
;
10
}
11
}
12
}
13
}
14
}
15
...
You 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, parse the attendees array using the code below:
01
...
02
else
if
(fieldName
=
=
'attendees'
){
03
if
(parser.getCurrentToken()
=
= JSONToken.START_ARRAY){
04
while
(parser.nextToken() !=
null
){
05
if
(parser.getCurrentToken()
=
= JSONToken.START_OBJECT){
06
//read GoogleEventAttendee object
07
GoogleEventAttendee gEventAttendee
=
(GoogleEventAttendee) parser.readValueAs(GoogleEventAttendee.
class
);
08
this
.attendees.add(gEventAttendee);
09
}
10
else
if
(parser.getCurrentToken()
=
= JSONToken.END_ARRAY){
11
break
;
12
}
13
}
14
}
15
}
16
...
After detecting the attendees array, the code uses the readValueAs() method to deserialize the JSON structure into theGoogleEventAttendee object automatically — in other words, without parsing the fields separately.
Demo App Walk-Through
Now that you know the basics of JSON handling, try walking through a demo application that integrates with the Google Calendar APIs and uses JSON format to send and receive calendar information. Before you can use the demo app, you have to go through the prerequisite steps below.
Prerequisites
Before you can use the demo app, you need to:
- 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.
Here's how.
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 for free.
Step 2: Install the Demo App Package
In a new browser tab, launch the installation of the demo app package into your Developer org using the URL in the link. Once the installation starts, click Continue at the Package Installation Details page, then approve the third-party website access and clickContinue.
Click Next at the Approve Package API Access page, then select Grant access to all users and click Next at the Choose Security Level page.
Click Install at the Install Package page, after which the package has been installed into your org.
Step 3: Create a Google APIs Project
In a web 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. This article explained the basics about handling JSON content in Apex. It provided a walk-through of the Force.com demo application that integrates with the Google APIs and uses JSON as the data-interchange format. The code samples provided in the article demonstrated how different serialization and deserialization options could be implemented in Apex.
Related Links
- Google Calendar APIs reference
- JSON documentation: http://json.org/
- Apex JSON documentation
- Unmanaged package with the demo app
About the Author
Shamil Arsunukayev is a Technical Architect at Comity Designs Inc. His primary focus is development of cloud applications, specifically Force.com applications and customizations. Shamil often participates in various Force.com developer challenges and hackathons. He can be found on @shamiltech and his blog assertequals.com
- Getting Started with Apex JSON
- Getting Started with Smartphone
- Getting Started With JasperReports
- Getting started with OpenCV
- Getting Started with DWR
- Getting Started With JasperReports
- Getting Started with MASM
- Getting started with BlazeDS
- Getting Started with RMAN
- Getting started with LAM
- Getting started with Davinci
- Getting Started with Monkey
- Getting Started with Boost
- Getting started with windbg
- Getting started with IUNIVERS
- Getting started with uClinux
- Getting Started with CVS
- Getting started with rrdtools
- Machine Learning week 1 Programming Excercise 数据归一化的代码 +画代价函数的学习曲线
- struts2标签截取字符串
- Android fill_parent、wrap_content和match_parent的区别
- leetcode || 76、Minimum Window Substring
- 用org.apache.commons.fileupload上传文件获取其他参数
- Getting Started with Apex JSON
- [LeetCode]Symmetric Tree
- java设计模式------单例模式
- 《Orange's 一个操作系统的实现》学习笔记--特权级代码段之间的转移(三)
- leetcode_Letter Combinations of a Phone Number
- 心绪不宁的时候就该写点东西,审视一下自己的内心吧
- Android 学习路线
- Java_语法基础_提防包装类型的null值
- 蓝桥Basic19完美的代价