+ Start a Discussion
Veena GopalVeena Gopal 

parsing json string using http://json2apex.herokuapp.com/

According to blog http://blog.adityanaag.com/22/Parsing+JSON+the+easy+way+using+Apex
when parsing a string 
{"size":141,"totalSize":141,"done":true,"queryLocator":null,"entityTypeName":"ApexCodeCoverageAggregate","records":[{"attributes":{"type":"ApexCodeCoverageAggregate","url":"/services/data/v33.0/tooling/sobjects/ApexCodeCoverageAggregate/715000000LxWDAA0"},"Id":"715000000LxWDAA0","ApexClassOrTrigger":{"attributes":{"type":"Name","url":"/services/data/v33.0/tooling/sobjects/ApexClass/01p000000C8J2AAK"},"Name":"MyCustomClass1"},"NumLinesCovered":0,"NumLinesUncovered":10},{"attributes":{"type":"ApexCodeCoverageAggregate","url":"/services/data/v33.0/tooling/sobjects/ApexCodeCoverageAggregate/715e0000000LxWEAA0"},"Id":"710000000LxWEAA0","ApexClassOrTrigger":{"attributes":{"type":"Name","url":"/services/data/v33.0/tooling/sobjects/ApexClass/01pe0000000C8JCAA0"},"Name":"MyCustomClass2"},"NumLinesCovered":7,"NumLinesUncovered":5}]}

produces below class
public class JSON2Apex {

	public class Attributes {
		public String type;
		public String url;
	}

	public class Records {
		public Attributes attributes;
		public String Id;
		public ApexClassOrTrigger ApexClassOrTrigger;
		public Integer NumLinesCovered;
		public Integer NumLinesUncovered;
	}

	public class ApexClassOrTrigger {
		public Attributes attributes;
		public String Name;
	}

	public Integer size;
	public Integer totalSize;
	public Boolean done;
	public Object queryLocator;
	public String entityTypeName;
	public List records;

	
	public static JSON2Apex parse(String json) {
		return (JSON2Apex) System.JSON.deserialize(json, JSON2Apex.class);
	}
}

but when i use json2apex to parse the same string i get as below:
//
// Generated by JSON2Apex http://json2apex.herokuapp.com/
//
// The supplied json has fields with names that are reserved words in apex
// and so can only be parsed with explicitly generated code, this option
// was auto selected for you.



public class JSON2Apex {
	
public static void consumeObject(JSONParser parser) {
		
Integer depth = 0;
		
do {
			
JSONToken curr = parser.getCurrentToken();
			
if (curr == JSONToken.START_OBJECT || 
curr == JSONToken.START_ARRAY) 
{

				depth++;
			} 
else if (curr == JSONToken.END_OBJECT || 
curr == JSONToken.END_ARRAY) {
	
		depth--;
			}
		} 
while (depth > 0 && parser.nextToken() != null);
	}

	
public class ApexClassOrTrigger {
		
public Attributes attributes {get;set;} 
		
public String Name {get;set;} 

		
public ApexClassOrTrigger(JSONParser parser) {
			
while (parser.nextToken() != JSONToken.END_OBJECT) {
				
if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
					
String text = parser.getText();
					
if (parser.nextToken() != JSONToken.VALUE_NULL) {
						
if (text == 'attributes') {
							
attributes = new Attributes(parser);
						} 
else if (text == 'Name') {
							
Name = parser.getText();
						} 
else {
							
System.debug(LoggingLevel.WARN, 'ApexClassOrTrigger consuming unrecognized property: '+text);
							consumeObject(parser);
						
}
					
}
				
}
			
}
		
}
	
}
	
	
public class JSON2Apex {
		
public Integer size {get;set;} 
		
public Integer totalSize {get;set;} 
		
public Boolean done {get;set;} 
		
public Object queryLocator {get;set;} 
		
public String entityTypeName {get;set;} 
		
public List<Records> records {get;set;} 


		
public JSON2Apex(JSONParser parser) {
			
while (parser.nextToken() != JSONToken.END_OBJECT) {
				
if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
					
String text = parser.getText();
					
if (parser.nextToken() != JSONToken.VALUE_NULL) {
						
if (text == 'size') {
							
size = parser.getIntegerValue();
						} 
else if (text == 'totalSize') {
							
totalSize = parser.getIntegerValue();
						} 
else if (text == 'done') {
							
done = parser.getBooleanValue();
						} 
else if (text == 'queryLocator') {
							
queryLocator = new Object(parser);
						} 
else if (text == 'entityTypeName') {
							
entityTypeName = parser.getText();
						} 
else if (text == 'records') {
							
records = new List<Records>();
							
while (parser.nextToken() != JSONToken.END_ARRAY) {
								
records.add(new Records(parser));
							}
						} else {
							
System.debug(LoggingLevel.WARN, 'JSON2Apex consuming unrecognized property: '+text);
							consumeObject(parser);
						}
					}
				}
			}
		}
	}
	
	
public class Attributes {
		
public String type_Z {get;set;} // in json: type
		
public String url {get;set;} 

		
public Attributes(JSONParser parser) {
			
while (parser.nextToken() != JSONToken.END_OBJECT) {
				
if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
					
String text = parser.getText();
					
if (parser.nextToken() != JSONToken.VALUE_NULL) {
						
if (text == 'type') {
							
type_Z = parser.getText();
						} 
else if (text == 'url') {
							
url = parser.getText();
						} 
else {
							
System.debug(LoggingLevel.WARN, 'Attributes consuming unrecognized property: '+text);
							consumeObject(parser);
						}
					}
				}
			}
		}
	}
	
	
public class Records {
		
public Attributes attributes {get;set;} 
		
public String Id {get;set;} 
		
public ApexClassOrTrigger ApexClassOrTrigger {get;set;} 
		
public Integer NumLinesCovered {get;set;} 
		
public Integer NumLinesUncovered {get;set;} 

		
public Records(JSONParser parser) {
			
while (parser.nextToken() != JSONToken.END_OBJECT) {
				
if (parser.getCurrentToken() == JSONToken.FIELD_NAME) {
					
String text = parser.getText();
					
if (parser.nextToken() != JSONToken.VALUE_NULL) {
						
if (text == 'attributes') {
							
attributes = new Attributes(parser);
						} 
else if (text == 'Id') {
							
Id = parser.getText();
						} 
else if (text == 'ApexClassOrTrigger') {
							
ApexClassOrTrigger = new ApexClassOrTrigger(parser);
						} 
else if (text == 'NumLinesCovered') {
							
NumLinesCovered = parser.getIntegerValue();
						} 
else if (text == 'NumLinesUncovered') {
							
NumLinesUncovered = parser.getIntegerValue();
						} 
else {
							
System.debug(LoggingLevel.WARN, 'Records consuming unrecognized property: '+text);
							consumeObject(parser);
						}
					}
				}
			}
		}
	}
	
	
	
public static JSON2Apex parse(String json) {
		
return new JSON2Apex(System.JSON.createParser(json));
	}
}

can anyone please help me in understanding how the blogger cleaned his code and came to such a simple code.​
Best Answer chosen by Veena Gopal
Shruti SShruti S
If the JSON2APEX App encounters a keyword in the JSON, then the parse code for the entire class will be automatically generated in the resulting Apex Class. It suffixes the member variable which is same as a keyword with '__Z'.
For example we have a JSON as below - 
{
    "case"  : "123",
    "email" : "xyz@123.com"
}
The Apex Class for this will be - 
public class Json2Apex {
    public String case;
    public String email;
}
In this case, the Apex Class will be wrong as case is a keyword and cannot be used as an identifier and hence JSON2APEX App will generate a parse code for this.

It is because of this generated parse code you are seeing a huge code in JSON2APEX App.

In the JSON which you had given in your example, there is a key as 'type' which is not really a keyword, but there exists a class named as type in Salesforce. Hence the JSON2APEX App automatically adds parse code for all the variables in the JSON. But type is actually not a keyword, hence there is an exception in this case. So you can actually remove the parse code and leave it as type instead of 'type__Z', just like what the blogger did.

All Answers

Shruti SShruti S
If the JSON2APEX App encounters a keyword in the JSON, then the parse code for the entire class will be automatically generated in the resulting Apex Class. It suffixes the member variable which is same as a keyword with '__Z'.
For example we have a JSON as below - 
{
    "case"  : "123",
    "email" : "xyz@123.com"
}
The Apex Class for this will be - 
public class Json2Apex {
    public String case;
    public String email;
}
In this case, the Apex Class will be wrong as case is a keyword and cannot be used as an identifier and hence JSON2APEX App will generate a parse code for this.

It is because of this generated parse code you are seeing a huge code in JSON2APEX App.

In the JSON which you had given in your example, there is a key as 'type' which is not really a keyword, but there exists a class named as type in Salesforce. Hence the JSON2APEX App automatically adds parse code for all the variables in the JSON. But type is actually not a keyword, hence there is an exception in this case. So you can actually remove the parse code and leave it as type instead of 'type__Z', just like what the blogger did.
This was selected as the best answer
Shruti SShruti S
Happy to help.

A json string can be converted into an instance of a class. For that we use the inbuilt method 'deserialize' of JSON class which is offered by Salesforce.

Imagine we have a class like this -
public class Student {
    public String fname;
    public String lname;
}

String json = '{"fname":"ABC", "lname":"XYZ"}';
And we want to convert the json to an instance of the student class. We can use the deserialize method for this and this is the way to do this -
( Student ) JSON.deserialize( json, Student.class )
The deserialize method accepts two arguments. The first one is the json string and the second argument is the name of the class whose instance we want to create. We need to suffix ".class" with the class name. And finally we need to type cast this.

This is the code the blogger has written in there.