3

I am implementing a custom REST API to support upserting a related set of records, similar to the Salesforce composite REST API. Main reason for that is because I want all DML operations to be part of a single transaction. I have a problem accessing the child records in the nested structure after deserializing them. For example, I can successfully deserialize a nested JSON structure containing one parent and one child record, both custom objects. Here's how I am doing that (just muck-about code while I get it going):

    while (parser.nextToken() != Null) {
        if (parser.getCurrentName() == 'records') {
            parser.nextValue();
            parents = (list<Parent_Object__c>)parser.readvalueas(list<SObject>.class);
            break;
        }
    }

Once that runs, I have the parent record(s) and can upsert them. I can also see that the child records are in the data structure, both from debug log and because if I serialize it back by calling JSON.serialize(parents) and check in the generated JSON. Here's the part of the System.debug(parent) with the child record in it:

...., "child_objects__r":[{"s":3,"v":{"new_control_systems_ (2 more) ...":"switch_only_1","quantity__c":"17","attributes":{"type":"child_object__c"}}}], ....

However, the problem comes when I try to get hold of a child to upsert it. Here's what I have:

for (Child_Object__c c: parent.Child_Objects__r) {
    c.parent__c = parent.Id;
    children.add(c);
}

It never gets into that loop.

I'm thinking I might change things to just pass through a flat list of SObjects to upsert but was hoping to keep close the spirit of the Salesforce composite API call and the parent child info is implicit in the structure.

Here's a cut down version of the JSON I am passing in:

{
    "records": [
        "custom_field__c": "blah",
        "ext_id__c": "abc123",
        "attributes": {
            "referenceId": "abc123",
            "type": "Parent_Object__c"
        },
        "child_objects__r": {
            "done": false,
            "totalSize": 1,
            "records": [
                {
                    "cust_field__c": "abc",
                    "child_ext_id__c": "abc123-1",
                    "attributes": {
                        "referenceId": "abc123-1",
                        "type": "Child_Object__c"
                    }
                }
            ]
        }
    ]
}

Added the "done" and "totalSize" after reviewing what Salesforce creates when serializing SObjects. Makes no difference if I set "done" to true or false.

  • Should the inner loop be over parent.Child_Objects__r.records? That is where all the field values will be. – Daniel Ballinger May 8 '16 at 22:15
  • Just tried... when I change it to Parent_Object__c.Child_Objects__r.records, it doesn't compile. I get the error "Invalid foreign key relationship: Parent_Object__c.Child_Objects__r" – donmac23 May 8 '16 at 22:19
  • I wonder if having the __c and __r suffixes in your JSON is causing some confusion. I might be easier to have distinct names in you JSON that don't follow Salesforce custom object and relationship naming conventions. Less likely to get mixed up. – Daniel Ballinger May 8 '16 at 22:22
  • I did that because that is how the composite API call does. Just tried changing Child_Objects__r to something else but I get an error upon deserializing: "System.JSONException: No such column 'Child_Objects' on sobject of type Parent_Object__c". Of course I could have whatever conventions I want but am trying to make it so I can just call parser.readvalueas(list<SObject>.class) and not do lots of explicit JSON parsing. – donmac23 May 8 '16 at 22:29
  • Maybe you could do a System.debug of parent before your for loop to see what state it is in. Or even serialize it again to see if it matches the input JSON. – Daniel Ballinger May 8 '16 at 22:39

Your Answer

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

Browse other questions tagged or ask your own question.