2

I have an Apex @AuraEnabled method that queries a collection of root objects and also several parent/child objects all at the same time. I have programmatic filtering of the child objects (returned in separate fields), but because I am also returning the root object, the child objects "leak" to the client-side via the relationship references (the __r fields) when the root object is serialized.

What is the cleanest way to only return the root object, given that e.g. at compile-time __r fields are not writeable? And my reading of the SObject Class clone method is that there is no option to discard the related objects?

PS

This:

// Don't want to leak data to the client-side through the __r fields
Root__c rootOnly = new Root__c();
Map<String, Object> m = root.getPopulatedFieldsAsMap();
for (String field : m.keySet()) {
    rootOnly.put(field, m.get(field));
}

suffers the problem of errors such as "CreatedById is not editable" but I'd like to keep that information. I'm starting to think that having a second query of just the root object is the only way to do this.

2

You're right that SObject.clone will maintain the existing relationship(s). An option is to construct a Map<String, Object> that mimics the SObject then turn that back into an SObject, something like:

Root__c root = ...;

// The remaining code works regardless of the type of SObject since it uses
// SObject API features
Map<String, Object> fields = root.getPopulatedFieldsAsMap();
Map<String, Object> rootOnlyMap = new Map<String, Object> {
        'attributes' => new Map<String, Object> {
                'type' => root.getSObjectType().getDescribe().name
        }
};

for (String fieldName : fields.keySet()) {
    Object fieldValue = fields.get(fieldName);
    
    if (!(fieldValue instanceof SObject) && !(fieldValue instanceof List<SObject>)) {
        rootOnlyMap.put(fieldName, fieldValue);
    }
}

SObject rootOnly = (SObject) JSON.deserialize(
        JSON.serialize(rootOnly),
        Type.forName(root.getSObjectType().getDescribe().name));

It is a bit "round the houses" but works from what I've tested.

3
  • Thanks Phil. But does this work-around not being able to set e.g. CreatedById? – Keith C Nov 27 '20 at 20:17
  • 1
    Should do since you just set that in the map and serialize and deserialize back into an SObject. – Phil W Nov 27 '20 at 20:27
  • Thanks Phil - sneaky I'll give it a go. – Keith C Nov 28 '20 at 0:03

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.