[SalesForce] JSON.deserialize on custom sObject not parsing related fields from lookup relationship

I've got a map whose values are a wrapper class. The wrapper class holds a custom sObject list, and the sObject in turn was queried to include related fields from a lookup relationship.

Problem is, when I use JSON.deserialize(jsonString, Map<Id, MapWrapper>.class), although the custom sObject is parsed, the related fields via the lookup relationship are not.

In prettified JSON, my serialized wrapper class (actually a map of ID to wrapper) looks like this, with the missing related fields highlighted :

{  
   "0011b00000Z6Pa8AAF":{               
      "entity":{                        
         "Id":"0011b00000Z6Pa8AAF",
         "Name":"Mohyee Holdings LLC"
      },
      "periodList":[  
         {  
            "Id":"a141b0000006lntAAA",
            "LLC_BI__Statement_Date__c":"2018-12-31",
            "LLC_BI__Source__c":"Tax Return",
            "LLC_BI__Number_of_Periods__c":12,
            "LLC_BI__Spread_Statement_Type__c":"a191b0000003gVZAAY",
            "LLC_BI__Spread_Statement_Type__r":{  
               "LLC_BI__Bundle__c":"a1G1b000000oreiEAA",
               "LLC_BI__Type__c":"UCA Cash Flow",
               "Id":"a191b0000003gVZAAY",
               "LLC_BI__Bundle__r":{  
                  "LLC_BI__Relationship__c":"0011b00000Z6Pa8AAF",
                  "Id":"a1G1b000000oreiEAA"
               }
            }
         }
      ]
   }
}

After I run JSON.deserialize(jsonString, Map<Id, MapWrapper>.class) I get

{0011b00000Z6Pa8AAF = MapWrapper:[  
      entity=Account:{  
         Id=0011b00000Z6Pa8AAF,
         Name=Mohyee Holdings LLC
      },
      periodList=(LLC_BI__Spread_Statement_Period__c:{  
         LLC_BI__Spread_Statement_Type__c=a191b0000003gVZAAY,
         Id=a141b0000006lntAAA,
         LLC_BI__Statement_Date__c=2018-12-31 00:00:00,
         LLC_BI__Number_of_Periods__c=12.0,
         LLC_BI__Source__c=Tax Return}
      )
   ]
}

Note that the related sObject LLC_BI__Spread_Statement_Type__r is no longer included in the LLC_BI__Spread_Statement_Period__c object after deserializing.

Here's the wrapper class that JSON.deserialize() is casting to:

public class MapWrapper{
    @AuraEnabled public Account entity{get;set;}
    @AuraEnabled public list<LLC_BI__Spread_Statement_Period__c> periodList {get;set;}      
}

Best Answer

You are simply being tripped up by default logging behavior. Just because system.debug(someInstance) does not show you some attributes does not mean they are not set. Specifically, logging any SObject does not show you parent values. This behavior is easy to demonstrate.

Run this script in Execute Anonymous:

Map<String, Object> data = new Map<String, Object>
{
    'Account' => new Map<String, Object> { 'Name' => 'ACME' }
};
Opportunity record = (Opportunity)JSON.deserialize(
    JSON.serialize(data), Opportunity.class
);
system.debug(record);
system.debug(record.Account);

Observe the logs:

Opportunity:{}
Account:{Name=ACME}

The lesson here is simple. Do not use system.debug to verify behavior, especially of complex object attributes.

Related Topic