function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
MrTheTylerMrTheTyler 

Determine the fields queried on an sobject

More of a theoretical question - in the displayfields function below is it possible to do what I've done in pseudocode?

 

main(){
  sobject acc = [select name, phone from account limit 1];
  displayfields(acc);
}

static void displayfields(sobject x){
  //somehow loop through the available fields on the sobject
  //and display them
  for(field f:x.fields) system.debug(f.fieldname);  //should print out "name" , "phone"
}

 

Thanks!

 

Tyler

 

salesforce expertsalesforce expert

let me know if this code helps you!

 

DescribeSObjectResult describeSObjectResult = connection.describeSObject("Case");
    Field[] fields = describeSObjectResult.getFields();
    Map fieldMap = new HashMap();
    for (int i = 0; i < fields.length; i++) {
      fieldMap.put(fields[i].getName(), fields[i]);
    }
MrTheTylerMrTheTyler

While very nice code for showing all fields defined on an sobject, I'm not sure it shows me what fields have been retrieved in a query.  For example:

 

void main(){
  sobject q1 = [select name, email from contact limit 1];
  sobject q2 - [select name, email, birthday from contact limit 1];

  f(q1);  //debugs "name", "email" 
  f(q2);  //debugs "name", "email", "birthday"
}

 

I could see using your code to get all the field names and then use a try catch block to brute force a solution.  Any idears on a more graceful solution?

 

 

Merry Christmas!!

 

Tyler

Andy BoettcherAndy Boettcher

If you're defining a static SOQL query - why do you need to know the fields?  I would think that you could use Dynamic SOQL and reference the string of fields you create in the query string?

MrTheTylerMrTheTyler

The question is, at this time, theoretical and aimed at getting a deeper understanding of sobject data structures.  However, I can imagine a utility routine that can be called from many different places, passing in different sobject types with varying subsets of their fields available.

 

Using @[Salesforce Expert]'s schema exploring code, I could see looping through every field available for a sobject type on a sobject instance and catching errors for accessing those unqueried fields - however, my gut tells me there should be some means for directly getting a set of field names queried and therefore available for a sobject instance.

 

 

Thanks for your time,

 

 

Tyler

Andy BoettcherAndy Boettcher

If we were in MS SQL land or another RDBMS, there are ways to find out that information rather easily.  However in SF - as far as my experience has shown me, you can ask the system questions about objects (getDescribe, etc) but you cannot ask it the specific question you are seeking.

 

If you find out otherwise, please comment back on this post - I'd be interested to hear how!

John Rogers 4John Rogers 4
This is a new feature in Summer 16! 

We’ve added a method on the Apex SObject class that makes it more efficient to iterate over fields that have been populated in memory.
Previously, iterating over just the populated the fields of an SObject involved some complicated programming. For example, if you queried an SObject using SOQL, it wasn’t easy to tell which fields were returned. In Summer ’16, we’ve introduced a new method on the SObject class that returns a map of populated field names and their corresponding values: Map<String, Object> getPopulatedFieldsAsMap()

http://releasenotes.docs.salesforce.com/en-us/summer16/release-notes/rn_apex_sobject_getmap.htm
Danny SalvadoriDanny Salvadori
You could do something around handling the SObjectException that's thrown when attempting to access an unqueried field, e.g.:
Account acc = [SELECT Id, Name, AnnualRevenue FROM Account LIMIT 1];
List<String> foundFields = new List<String>();
for (Schema.SObjectField field : Schema.SObjectType.Account.fields.getMap().values()) {
    String fieldName = field.getDescribe().getName();
    try {
        Object arbitraryAssignment = acc.get(fieldName); // Throws exception if not queried
        foundFields.add(fieldName);
    } catch (System.SObjectException ex) {
        // Do nothing; we're 99% sure this is going to happen a lot
    }
}
System.debug(foundFields); // [Id, Name, AnnualRevenue]
This is hardly the most efficient code in the world, however!
 
Danny SalvadoriDanny Salvadori

Actually, looks like there's a method for this now: `getPopulatedFieldsAsMap`

Account a = [select Id,Name from Account where LIMIT 1];
Map<String, Object> fieldsToValue = a.getPopulatedFieldsAsMap();

for (String fieldName : fieldsToValue.keySet()){
    System.debug('field: ' + fieldName + '; value: ' + 
        fieldsToValue.get(fieldName));
}
 

https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_sobject.htm#apex_System_SObject_getPopulatedFieldsAsMap