Essentially what I'm looking for is the Apex equivalent of the javascript delete operator

The reason I want to do this is that I want to store data in the standard Contact.Email field, but I need to handle the possibility that the data coming in could cause a save error with a INVALID_EMAIL_ADDRESS status code. I want to be able to detect the error, and retry the upsert with the value provided for the email address being stored into a new custom text field instead. To do this, I need to clear the value in the object's Email field. Since this is an upsert operation, I don't want to set the value of the field to NULL since that will clear the value in the database, which I would want to leave intact if it is already present.

Basically, what I'm looking for is the easiest way to get from:

Contact:{LastName=LastName, Email=FirstName.LastName@@Company.com, Id=003p000000LO97zAAD, ...}


Contact:{LastName=LastName, Email__c=FirstName.LastName@@Company.com, Id=003p000000LO97zAAD, ...}

and specifically not:

Contact:{LastName=LastName, Email=null, Email__c=FirstName.LastName@@Company.com, Id=003p000000LO97zAAD, ....}
  • You're going to need to do it in a couple steps.
    – Adrian Larson
    Commented Nov 22, 2017 at 15:46
  • 2
    This capability does not exist in apex today. One way or another you'll need to construct a new SObject instance to do this Commented Nov 23, 2017 at 2:52
  • Hi Martin, thoughts on renaming this question to use the word "sobject" instead of "object"? When I read object I thought you meant needing to use metadata api to physical alter the structure of the object/table, not your apex variable. Or re-phrase as "object variable"? Thanks!
    – Doug Ayers
    Commented Nov 23, 2017 at 5:28
  • 1
    @DougAyers I was using the term object in the sense of an instance of a class, but specifying that the object inherits from sObject does give you more to work with, and I was specifically concerned about the effects on DML operations, so I'd be willing to update the question.
    – martin
    Commented Nov 23, 2017 at 6:34

3 Answers 3


This can be done using combination of serialize and deserialize tricks with SObject and Map. In short, you serialize your original sobject into JSON then deserialize it into untyped Map then modify the map's keys to add/remove any fields you want - or don't want - set. Then serialize the map back into JSON then deserialize it into your typed SObject.

// start with your original sobject
Account acct1 = new Account(
    name = 'Turkey',
    type = 'Gobble'
System.debug( 'Step 1. Account object: ' + acct1 );

// Step 2. Get map of the sobject fields
// In this variant, the populated fields map is read-only so pass it into another map to get an editable copy
Map<String, Object> acctMap1 = new Map<String, Object>( acct1.getPopulatedFieldsAsMap() );
System.debug( 'Step 2. Account populated fields map: ' + acctMap1 );

// Another way to do Step 2 is good ol' serialize/deserialize trick
Map<String, Object> acctMap2 = (Map<String, Object>) JSON.deserializeUntyped( JSON.serialize( acct1 ) );
System.debug( 'Another way to do Step 2. Account serialized as json then deserialized back into untyped map: ' + acctMap2 );

// Step 3. Remove any fields you don't want
acctMap1.remove( 'Type' );
System.debug( 'Step 3. Remove undesired field "Type" from map: ' + acctMap1 );

// Step 4. Convert the map into sobject using the good ol' serialize/deserialize trick
Account acct2 = (Account) JSON.deserialize( JSON.serialize( acctMap1 ), Account.class );
System.debug( 'Step 4. Account after serializing map of our desired fields into json then deserializing the json back into sobject: ' + acct2 );
  • 1
    How would one go about doing this kind of thing with several layers of nested JSON?
    – Genko
    Commented Dec 12, 2018 at 17:51

I'd recommend you try to upsert your records via the Database.upsert method.

Database.UpsertResult resultList = Database.upsert(contactList, Contact.Id, false);

resultList will now contain your results.

// New list of contacts
List<Contact> contactList2 = new List<Contact>();

// Check each result for success
for(Integer i = 0; i < resultList.size(); i++)
    Database.UpsertResult result = resultList.get(i);

        for(Database.error singleError : result.getErrors())
            if(singleError.getStatusCode() == Database.StatusCode.INVALID_EMAIL_ADDRESS)
                Contact c = contactList.get(i);
                c.Email__c = c.Email;

Check out Database.UpsertResult and Database.Error.

Basically your allowing SF to upsert each row individually and then evaluate the results. You should - of course - handle other errors as well.

  • So far so good, the problem is with the next step though. How do you get rid of the Email field in c so you can re-upsert that object without erasing a value already stored in the database or re-encountering the same error?
    – martin
    Commented Nov 22, 2017 at 16:01
  • @martin I guess you can instantiate a new contact instead of using the one in the list: Contact c = new Contact(Id = contactList.get(i).Id);
    – Novarg
    Commented Nov 23, 2017 at 8:48
  • @martin Or re-query the records that fail instead of adding them to contactList2. Then populate your custom email field and upsert.
    – Christoph
    Commented Nov 23, 2017 at 11:00
  • @Novarg I agree that this will probably require the construction of a new object instance.
    – martin
    Commented Nov 23, 2017 at 12:51
  • @Christoph These records are coming in through push notifications from an external system. In this case I do also have the ability to make a callout to re-query these records, but I wouldn't want to have to do it that way.
    – martin
    Commented Nov 23, 2017 at 12:52

Came across a different use-case for needing to do this:

There was a long-running, Stateful Batch Job that queried records in the start(), modified them in the execute() and updated them in the finish().

This resulted in a Lost Update concurrency problem if a user modified any of the queried fields while the batch was running.

Wrote a generic utility function:

public static List<Object> removeProperties(Type objectType, List<Object> objects, String[] propertiesToRemove){
   // serialize / deserialize into a generic List<Map<String, Object>>
   List<Object> deserializedList = (List<Object>) JSON.deserializeUntyped(JSON.serialize(objects));

    // For each object, remove each property
    for (Object deserialized : deserializedList) {
        Map<string, Object> obj = (Map<string, Object>) deserialized;
        for(string property : propertiesToRemove){
    // serialize / deserialize back to object type
    return (List<Object>) JSON.deserialize(JSON.serialize(deserializedList), objectType); 

//... test
Account[] ogList = new Account[]{
   new Account(Name='foo1', Website = 'testing.com')

Account[] cleanedList = (List<Account>) removeProperties(
    List<Account>.class, ogList, new string[]{'Website'}


System.assertEquals(cleanedList.size(), ogList.size());
system.assert(cleanedList[0].Website == null);

This is basically the same as the @Doug Ayers answer, but maybe more performant for bulk use cases.

You must log in to answer this question.

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