5

I am calling a REST endpoint (of another Salesforce instance) and I am getting the following response:

[{
    "attributes": {
        "type": "Job__c",
        "url": "/services/data/v29.0/sobjects/Job__c/a03e0000004AZfcAAG"
    },
    "Web_Scribble_Record_Link__c": "http://www.google.com",
    "Organization_Type__c": "Ed Support Org - Education Technology",
    "Job_Type__c": "Job Type - Field",
    "Position_Type__c": "Full-Time",
    "Experience_Level__c": "2 - 5 Years",
    "Job_State__c": "CA",
    "Employer_State__c": "California",
    "Employer_Name__c": "Joes Town Inc",
    "Employer_City__c": "Los Angeles",
    "Application_Link__c": "http://www.myapplink.com",
    "Organization__c": "001e000000PBP4oAAH",
    "Id": "a03e0000004AZfcAAG",
    "Job_Title__c": "Director of Events",
    "Job_City__c": "Brea"
}, {
    "attributes": {
        "type": "Job__c",
        "url": "/services/data/v29.0/sobjects/Job__c/a03e0000004AZqkAAG"
    },
    "Web_Scribble_Record_Link__c": "http://www.yahoo.com",
    "Organization_Type__c": "Government Ed Agency - State",
    "Job_Type__c": "Job Type - Field",
    "Position_Type__c": "Part-Time",
    "Experience_Level__c": "Less than 2 Years",
    "Job_State__c": "CA",
    "Employer_State__c": "California",
    "Employer_Name__c": "Joes Town Inc",
    "Employer_City__c": "Los Angeles",
    "Application_Link__c": "http://www.myapplink.com",
    "Organization__c": "001e000000PBP4oAAH",
    "Id": "a03e0000004AZqkAAG",
    "Job_Title__c": "Sr. Director of Fun",
    "Job_City__c": "Brea"
}]

The object from the remote instance is not present in my Salesforce instance so I want to cycle through the values and map them to a different object / fields in my instance.

If I strip out the square braces on the beginning / end I can use the following code:

    Map<String, Object> m = 
       (Map<String, Object>)
          JSON.deserializeUntyped(ERS);

The problem is that I think the map is not seeing two separate objects. So I think i am only getting one of the two results. Perhaps I need to feed the results into a list and then iterate them into the map but not sure how that syntax should look.

  • Why not just create the Job__c SObject in your org (you could give it a label of RemoteOrgJob and API name of Job__c) ? No data would ever be stored but you could deserialize in one statement. No tab need ever be visible. – cropredy Oct 28 '14 at 16:33
  • crop1645 its a very reasonable suggestion. I'm still hoping to handle the heavy lifting via the codeand avoid creating the extra meta-data. But I do concede that solution will get the job done. And if I don't find a way to parse the data it will be the road I go down. – Joseph U. Oct 28 '14 at 16:50
3

You can map the object to an array, which is what you should be doing, as it is an array.

Map<String, Object>[] results = (Map<String, Object>[])JSON.deserializeUntyped(ERS);
for(Map<String, Object> result: results) {
    // Handle each record here
}

EDIT: I just tried to set up a working example, and I found that the runtime system is a bit... awkward. It insists that the Object couldn't possibly be a List<Map<String, Object>>, so you may need to do something like this:

String src = '[{ "attributes": { "type": "Job__c", "url": "/services/data/v29.0/sobjects/Job__c/a03e0000004AZfcAAG" }, "Web_Scribble_Record_Link__c": "http://www.google.com", "Organization_Type__c": "Ed Support Org - Education Technology", "Job_Type__c": "Job Type - Field", "Position_Type__c": "Full-Time", "Experience_Level__c": "2 - 5 Years", "Job_State__c": "CA", "Employer_State__c": "California", "Employer_Name__c": "Joes Town Inc", "Employer_City__c": "Los Angeles", "Application_Link__c": "http://www.myapplink.com", "Organization__c": "001e000000PBP4oAAH", "Id": "a03e0000004AZfcAAG", "Job_Title__c": "Director of Events", "Job_City__c": "Brea"}, { "attributes": { "type": "Job__c", "url": "/services/data/v29.0/sobjects/Job__c/a03e0000004AZqkAAG" }, "Web_Scribble_Record_Link__c": "http://www.yahoo.com", "Organization_Type__c": "Government Ed Agency - State", "Job_Type__c": "Job Type - Field", "Position_Type__c": "Part-Time", "Experience_Level__c": "Less than 2 Years", "Job_State__c": "CA", "Employer_State__c": "California", "Employer_Name__c": "Joes Town Inc", "Employer_City__c": "Los Angeles", "Application_Link__c": "http://www.myapplink.com", "Organization__c": "001e000000PBP4oAAH", "Id": "a03e0000004AZqkAAG", "Job_Title__c": "Sr. Director of Fun", "Job_City__c": "Brea"}]';
List<Object> results = (List<Object>)JSON.deserializeUntyped(src);
for(Object result: results) {
    Map<String, Object> subResult = (Map<String, Object>) result;
    // use subResult here to map to another object
}
  • That's horribly confusing syntax for declaring a List/Array of Maps. Why oh why not List<Map<String, Object>> results? – Charles Koppelman Oct 28 '14 at 17:12
  • @CharlesKoppelman I use that syntax when I can probably because it's shorter and I find it easier to understand, given my history of C/C++ for the past few decades. Nothing saying you can't use List<Map<String, String>> if it suits your coding style. Unfortunately, Apex Code doesn't allow things like Integer[][], which I prefer over List<List<Integer>>. – sfdcfox Oct 28 '14 at 17:21
2

Assuming you don't want to create the object as suggested by crop1645, I would build a class using JSONtoApex, but then parse the response as a list if it will always be returned as a JSON array.

public class JOBExample {

    public String Web_Scribble_Record_Link;
    public String Organization_Type;
    public String Job_Type;
    public String Position_Type;
    public String Experience_Level;
    public String Job_State;
    public String Employer_State;
    public String Employer_Name;
    public String Employer_City;
    public String Application_Link;
    public String Organization;
    public String Id;
    public String Job_Title;
    public String Job_City;


    public static List<JOBExample> parseaslist(String json) {
        //Clean __c from field references as you can't use in non-sObject field references
        String sCleanedJSON = json.replaceall('__c', '');
        return (List<JOBExample>) System.JSON.deserialize(sCleanedJSON, List<JOBExample>.class);
    }

}

You can then get back an standard List from the JSON like this:

String s = [returned JSON String];
 List<JOBExample> jobs = JOBExample.parseaslist(s);
 system.debug(jobs[0]); 
 system.debug(jobs[1]);
  • 1
    I'd be hesitant to use replaceAll, though. It's probable, though admittedly rare, that you might lose data. Consider { "Application_Link__c": "http://www.contoso.com/app/Service?code=some__code" } (taken literally, for sake of argument). Especially if it's a Visualforce page in a managed package, whose page name starts with "c". – sfdcfox Oct 28 '14 at 17:27
1

I would add outside curly braces to make the response an object, instead of the response being an array. Then you can have the wrapper object be an array of two inner response objects. If that makes any sense. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.