61

I have a contact in a generic sObject in apex and while I'm able to easily get detail field values using

sObject.get('MyContactField__c')

I'm not able to get fields off the related parent object, and I'm sure the related field is in memory, based on the debug logs. This returns a runtime error:

sObject.get('Account.MyAccountField__c')

with the error

Invalid field Account.MyAccountField__c' for Contact

How do I get a field value off of a parent on a generic sObject?

greenstork
  • 14,752
  • 2
  • 44
  • 71

1 Answers1

101

You need getSobject() to traverse relationship "up" in a dynamic way.

sObject acc = [SELECT Owner.Profile.Name FROM Account LIMIT 1];
String profileName = (String) acc.getSobject('Owner').getSobject('Profile').get('Name');
System.debug(profileName);

Check all dynamic get* methods in the Sobject instance methods docs.

Caspar Harmer
  • 20,414
  • 4
  • 33
  • 68
eyescream
  • 24,045
  • 5
  • 55
  • 92
  • 11
    As an added bonus, you can also use getsObjects() to go the other way down the tree: e.g. List so = [Select Id, (Select Id from Contacts) from Account LIMIT 10]; List cons = so[0].getSObjects('Contacts'); – BritishBoyinDC Jan 22 '14 at 00:24
  • @BritishBoyinDC yep, that's why I pointed to all "get" methods! :) – eyescream Jan 22 '14 at 00:26
  • Just took me a while to realize that the phrase 'Returns the values for the specified field.' meant I could also get back the whole list...think the docs could use some additional detail...! – BritishBoyinDC Jan 22 '14 at 00:40
  • 10
    In case it helps someone else (I was wondering this): Using the '__r' will work. So if your dynamic code has something like List sList = [Select Name, Custom__r.Name from Contact]; it can be addressed with sList[0].getSobject('Custom__r').get('Name'); – HungryBeagle May 05 '15 at 13:35
  • The link was dead - edited. – Caspar Harmer Aug 27 '17 at 22:07
  • 2
    Probably would be worth adding checks for a null parent if you were going to genericize this functionality. I guess in this case though neither parent is nillable. – Adrian Larson Oct 10 '17 at 12:49
  • @AdrianLarson how do we check for fields that does not have value for example , in my case (String)obj.getSObject('Account').get('Name') sometime does not have value and apex is throwing an error in that case to counter this I have applied obj.getSObject('Account') !=null check but seems not working at all – Hunt Jan 23 '20 at 05:07
  • You should consider asking that as its own question @Hunt – Adrian Larson Jan 23 '20 at 05:24
  • 1
    @Hunt null check works for me, definitely post new question? sObject o = [SELECT Manager.Name FROM User LIMIT 1]; sObject manager = o.getSobject('Manager'); String name = manager != null ? (String) manager.get('Name') : 'Nope'; System.debug(name);. You could also SELECT ManagerId and check that... for related lists - I think list will always be there (never null value) but it's perfectly OK for it to be isEmpty(). – eyescream Jan 23 '20 at 06:26
  • 2
    For null checks, using the save navigation operator should do the trick: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_SafeNavigationOperator.htm – DavidSchach Jul 22 '21 at 21:38