2

I like the way JavaScript lets you easily overlay two objects, retaining the properties of both:

let obj1 = {name: 'Foo', quantity: 3};
let obj2 = {name: 'Bar', description: 'A very nice bar'};
// Merge the objects. Where these object share properties, obj2 will "win"
let newObj = {...obj1, ...obj2}; 
console.log(JSON.stringify(newObj));
// Console output:
// {'name': 'Bar', 'quantity': 3, 'description': 'A very nice bar'};

I often find myself needing to do something similar in Apex when dealing with SObject records of the same type. For example, when dealing with duplicates, or when working with dummy SObject records from test utilities.

I have a method for this, but it feels pretty heavy for what ought to be a simple task, relying (as it does) on a getDescribe() call:

// Push all populated, updateable field values from one SObject to another 
// SObject of the same type
public static SObject transferSObjectFieldValues(
    SObject targetObject, 
    SObject sourceObject, 
    Boolean writeBlank
) {
    Map<String, Schema.SObjectField> fieldMap = targetObject.getsObjectType()
        .getDescribe().fields.getMap();
    Map<String, Object> sourceFields = sourceObject.getPopulatedFieldsAsMap();
    for (String fieldName : sourceFields.keySet()) {
        Object value = sourceFields.get(fieldName);
        if (fieldMap.containsKey(fieldName)
            && fieldMap.get(fieldName).getDescribe().isUpdateable()
            && (writeBlank || 
                (value != null && 
                    !(value instanceof String && 
                        String.isBlank((String)value))))) {
            targetObject.put(fieldName, sourceFields.get(fieldName));
        }
    }
    return targetObject;
}

Is there something more lightweight and straightforward I could be doing?

3
  • Wouldn't Sobject clone method be helpful in your use case? Also you can use getPopulatedFieldsAsMap to get the populated fields and iterate over them to clone
    – manjit5190
    Jul 6, 2020 at 21:14
  • Cloning doesn't get me anywhere, because I want to retain the field values from both SObject variables, as long as they're populated (while defining which variable will "win" when both have the same fields populated). And as you can see, I'm using getPopulatedFieldsAsMap() already, but it seems like you still need a getDescribe() call, or you end up hitting "Field is not writeable" exceptions when you try to loop through that map and assign its values. Jul 6, 2020 at 21:21
  • 1
    Well then I think this method is fine. We are using Json serialized and then deserialization by adding both sobject values in a map and do the same thing you are doing but we have do a cleanup of the fields before we send them for cloning, that does reduces some code. I would love to see if anyone has different ideas.
    – manjit5190
    Jul 6, 2020 at 21:30

0

You must log in to answer this question.

Browse other questions tagged .