I am writing an async apex trigger for Opportunity.

The trigger gives me an OpportunityChangeEvent object which has all the fields of Opportunity (in addition to fields like "ChangeEventHeader")

Now my downstream service method expects a "SObject" in its parameter. How do I convert my changeEvent object to a sObject?

I tried converting the event to a map and populating the values to a new Opportunity

    OpportunityChangeEvent event = Trigger.New.get(0);
    Map<String, Object> eventMap = event.getPopulatedFieldsAsMap();
    eventBus.changeEventHeader changeEventHeader = event.ChangeEventHeader;
    String recordId = changeEventHeader.recordIds.get(0);

    SObject newObj = Opportunity.sObjectType.newSObject();
    for(String changedField: changeEventHeader.changedFields) {
        newObj.put(changedField, eventMap.get(changedField));

The problem with this approach is I am not able to set read-only fields like LastModifiedDate I get the error Field LastModifiedDate is not editable}

Another I tried was to convert the map to json and deserialize it to Opportunity

Map<String, Object> sObjectMap = new Map<String, Object>();
for(String changedField: changeEventHeader.changedFields) {
   sObjectMap.put(changedField, eventMap.get(changedField));
String sObjectMapJson = Json.serialize(sObjectMap);
SObject newObj = (Opportunity)JSON.deserialize(sObjectMapJson, Opportunity.class);

This works, but seems like a very convoluted way of achieving this.

Is there a native way (or atleast a more straightforward way) of getting an Opportunity object from a Change Event object?

  • If you absolutely need all the fields, including read-only fields, formulas, etc, JSON is the way to go.
    – sfdcfox
    Commented Feb 11 at 15:49


You must log in to answer this question.

Browse other questions tagged .