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.

1 Answer 1

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
    Commented Nov 27, 2020 at 20:17
  • 1
    Should do since you just set that in the map and serialize and deserialize back into an SObject.
    – Phil W
    Commented Nov 27, 2020 at 20:27
  • Thanks Phil - sneaky I'll give it a go.
    – Keith C
    Commented Nov 28, 2020 at 0:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .