Apex Clear all fields for a SObject record

The clearOutRecords would iterate all the fields passed as the currentRecord, then:
1. Exclude the fields as part of the fieldsToExcludeForClearOut Set and relationship fields
2. Check if the field is not null and updateable
3. Special logic to set fields to predefined values
4. Set all other fields to null
5. Return the SObject with fields as null


private static Set<String> fieldsToExcludeForClearOut = new Set<String>{'Cases', 'DoNotCall', 
'HasOptedOutOfFax', 'HasOptedOutOfEmail', 'LastName', 
'FirstName', 'Email', 'AccountId', 'CreatedDate',
'IsDeleted','Interval__c','OwnerId',
'OtherGeocodeAccuracy','MailingGeocodeAccuracy',
'BillingGeocodeAccuracy','ShippingGeocodeAccuracy'};

    public SObject clearOutRecords(SObject currentRecord, String sObjectName){
      SObjectType objToken = Schema.getGlobalDescribe().get(sObjectName);
      DescribeSObjectResult objDef = objToken.getDescribe();
      Map<String, SObjectField> fieldsSobject = objDef.fields.getMap();
      Map<String, Object> fields = currentRecord.getPopulatedFieldsAsMap();
      Type classType = Type.forName(sObjectName);
      SObject mergedRecord = (SObject)JSON.deserialize('{}', classType);
      for (String field : fields.keySet()){
        if (!fieldsToExcludeForClearOut.contains(field) && !field.contains('__r')){
          if (currentRecord.get(field)!=null && fieldsSobject.get(field).getDescribe().isUpdateable()){
            if ('User_Status__c'.equals(field)){
              mergedRecord.put(field, 'Incomplete');
            } else if ('Is_Mail_Same_As_Home__c'.equals(field)){
              mergedRecord.put(field, false);
            } else {
              mergedRecord.put(field, null);
            }
            } else if ('Id'.equals(field)){
            mergedRecord.put(field, currentRecord.get(field));
          }
        }
      }
      return mergedRecord;
    }

Initializing the clearOutRecords method

1. Query the fields that you would like to clear
2. Pass the Object to the clearOutRecords method

Contact queryContact = [Select Id, FirstName, LastName, Email, Birthdate, MailingState, Age__c from Contact where MailingState!=null limit 1 ];

Contact clearedOutContact = (Contact)App_Service.instance.clearOutRecords(queryContact, 'Contact');
        

Output

Contact:{Id=0036300000TQZIwAAP, Birthdate=null, MailingState=null}

Apex Compare two Records and Merge updated fields

When you have two record, one being the existing queried record and the other the updated record. To merge the original with the updated field without committing the changes you can iterate the current record’s fields and check which of the fields changed. Update the changed fields to the new updated fields value. Now we have an merged record. Here is how I went about doing it.

Original SObject record

{"Account_Type__c":"Managed","Amount__c":50.00,"Category__c":"Deposit",
"Description__c":"Deposit","End_Date__c":"2020-03-31T15:06:57.000+0000",
"Frequency__c":"Monthly"}

Update SObject record

{"Amount__c":500.0,"Id":"a0L63000000qc43EAA","Frequency__c":"Annually"}

Merge two records with changes

private static Set<String> fieldsToExclude = new Set<String>{'OwnerId','OtherGeocodeAccuracy','MailingGeocodeAccuracy','BillingGeocodeAccuracy','ShippingGeocodeAccuracy'};
public SObject mergeRecords(SObject updatedRecord, SObject currentRecord, String sObjectName){
  SObjectType objToken = Schema.getGlobalDescribe().get(sObjectName);
  DescribeSObjectResult objDef = objToken.getDescribe();
  Map<String, SObjectField> fields = objDef.fields.getMap();
  Type classType = Type.forName(sObjectName);
  SObject mergedRecord = (SObject)JSON.deserialize('{}', classType);
  for (String field : fields.keySet()){
    if (!fieldsToExclude.contains(fields.get(field).getDescribe().getName()) && (fields.get(field).getDescribe().isUpdateable() || fields.get(field).getDescribe().isCreateable())){
        if (updatedRecord.get(field)!=null){
        	mergedRecord.put(field, updatedRecord.get(field));
    	} else if (currentRecord.get(field)!=null){
        	mergedRecord.put(field, currentRecord.get(field));
    	}
    }
  }
  return mergedRecord;
}

Test that fields were merged correctly

@isTest static void testMergeRecords(){
  String currentRecordJSON = '{"Id":"a0L63000000qc43EAA","Account_Type__c":"Managed","Amount__c":50.00,"Category__c":"Deposit","Description__c":"Deposit","End_Date__c":"2020-03-31T15:06:57.000+0000","Frequency__c":"Monthly"}';
  String updatedRecordJSON = '{"Amount__c":500.0,"Id":"a0L63000000qc43EAA","Frequency__c":"Annually"}';
  Type classType = Type.forName('Account');
  SObject currentRecord = (SObject)JSON.deserialize(currentRecordJSON, classType);
  SObject updatedRecord = (SObject)JSON.deserialize(updatedRecordJSON, classType);
  Test.startTest();
    SObject mergedRecord = mergeRecords(updatedRecord, currentRecord, 'Account');
    System.assertEquals(mergedRecord.get('Amount__c'), 500.0);
    System.assertEquals(mergedRecord.get('Frequency__c'), 'Annually');
    System.assertEquals(mergedRecord.get('Account_Type__c'), 'Managed');
    System.assertEquals(mergedRecord.get('Category__c'), 'Deposit');
  Test.stopTest();
}