Handling JSON in Apex Shamil Arsunukayev Technical Architect, Comity Designs Inc. @shamiltech Agenda System.JSON System.JSONGenerator System.JSONParser Demo: Google Calendar APIs + JSON + Apex Q&A System.JSON JSON.serialize: Account acctOne = [SELECT id, name FROM Account LIMIT 1]; String acctJSON = JSON.serialize(acctOne); JSON.deserialize: Account acctTwo = (Account) JSON.deserialize(acctJSON, Account.class); Minimum number of script statements No need to use Dynamic Apex to inspect the metadata, it’s all automatic! CalendarList Resource JSON { "kind": "calendar#calendarListEntry", "etag": etag, "id": string, "summary": string, "hidden": boolean, … "defaultReminders": [ { "method": string, "minutes": integer } ] GoogleCalendar Apex Class public class GoogleCalendar { public String id; public String kind; public String etag; public String summary; public Boolean hidden; … public List<GoogleReminderOverride> defaultReminders; } System.JSON public String serialize() { return JSON.serialize(this); } public void deserialize(String jsonString) { GoogleCalendar gCal = (GoogleCalendar) JSON.deserialize(jsonString, GoogleCalendar.class); … } Notice how Apex objects are used instead of sObjects System.JSON Note: If GoogleCalendar Apex class didn’t have a field or fields to match the CalendarList JSON structure, the JSON.deserialize() method would have failed with the “System.JSONException: Unknown field field_name “ exception JSONGenerator Contains methods used to serialize Apex objects into JSON content using the standard JSON encoding. Useful for wrapping or aggregating values Can be used instead of the JSON.serialize() if the latter could not be used List<Contact> contacts = [Select Id, Name From Contact]; generator.writeStartObject(); generator.writeNumberField(‘count’, contacts.size()); generator.writeEndObject(); String jsonString = generator.getAsString(); Event Resource JSON { “summary": string, “end": { "date": date, … }, "attendees": [ { "email": string, … } ], "reminders": { "useDefault": boolean, "overrides": [ { "method": string, "minutes": integer } ] } <-------- ‘end’ is a reserved Apex keyword <-------- ‘date’ is a reserved Apex keyword GoogleCalendarEvent Apex Class public class GoogleCalendarEvent { public String summary; … public GoogleEventTime start; public GoogleEventTime gEnd; //renamed ‘end’ public List<GoogleEventAttendee> attendees; public GoogleReminder reminders; } JSONGenerator JSONGenerator gen = JSON.createGenerator(true); gen.writeStartObject(); gen.writeStringField('summary', ‘New event’); gen.writeFieldName('start'); gen.writeStartObject(); gen.writeObjectField('dateTime', System.now().addDays(1)); //or gen. writeDateTimeField('dateTime', System.now().addDays(1)); gen.writeEndObject(); { “summary”: “New event", "start": { "dateTime": "2012-03-16T18:03:32-08:00“ }, JSONGenerator gen.writeFieldName('reminders'); gen.writeObject(reminders); //reminders is a GoogleReminder object … "reminders": { "useDefault": false, "overrides": [ { "method": "email", "minutes": 1 }, { "method": "email", "minutes": 2 } ] }… GoogleReminder Apex Class public class GoogleReminder { public Boolean useDefault; public List<GoogleReminderOverride> overrides; } public class GoogleReminderOverride { public String method; public Integer minutes; } JSONGenerator gen.writeFieldName('attendees'); gen.writeStartArray(); 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(); … String jsonString = gen.getAsString(); //create a JSON string JSONGenerator "attendees": [ { "email": "attendeeOne@gmail.com", "optional": false, "additionalGuests": 1 }, { "email": "attendeeTwo@gmail.com", "optional": true, "additionalGuests": 2 }, ... ] JSONParser Generally, JSONParser is useful for grabbing specific pieces of data without the need for a structure such as an Apex class 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(); } }} JSONParser "attendees": [ { "email": "attendeeOne@gmail.com", "optional": false, "additionalGuests": 1 }, { "email": "attendeeTwo@gmail.com", "optional": true, "additionalGuests": 2 }, ... ] JSONParser … if(fieldName == 'attendees'){ if(parser.getCurrentToken() == JSONToken.START_ARRAY){ while(parser.nextToken() != null){ if(parser.getCurrentToken() == JSONToken.START_OBJECT){ GoogleEventAttendee gEventAttendee = (GoogleEventAttendee) parser.readValueAs(GoogleEventAttendee.class); this.attendees.add(gEventAttendee); } else if(parser.getCurrentToken() == JSONToken.END_ARRAY){ break; }}}} Demo: Google Calendar APIs + JSON + Apex Thank you Questions & Answers