6

I have some code that queries some fields from an object. I then use the schema to loop over all of the fields of an object. Is there a way, while I'm looping through the schema to tell if I had queried for a field before I try to use the sobject.get method?

List<Account> accs = [SELECT RecordTypeId, Name FROM Account];

List<Schema.SObjectField> fields = Schema.SOBjectType.Account.fields.getMap().values();
for (Account acc: accs)
{
  for (Schema.SObjectField field: fields)
  {
    //This will fail if I did not query for the field
    Object sField = acc.get(field.getDescribe().getName());
  }
}

4 Answers 4

9

Use Map<String, Object> getPopulatedFieldsAsMap() method on the sobject. It gives you a map of fields and values that got queried.

Please refer to this release notes for more information: (http://releasenotes.docs.salesforce.com/en-us/summer16/release-notes/rn_apex_sobject_getmap.htm)

1
  • Unfortunately, this method won't include ALL fields that were in the SOQL query - it will only return fields with non-null values
    – smohyee
    Commented May 20, 2021 at 14:07
6

I just came up with an idea:

try
{
  Object sfield = audit.get(fromName);
} catch (Exception e)
{
  continue;
}

Does anyone have a better idea without catching it if there is an error though?

1
  • 1
    This is generally very bad practice to use a try catch as a part of regular code flow.
    – Jake
    Commented Jul 29, 2021 at 2:28
1

the only other way to do this besides a try/catch is to write your query dynamically so that you get every field.

Example:

string queryString = 'SELECT ';
for(string field:Schema.SOBjectType.Account.fields.getMap().values())
    queryString += field+',';
queryString = queryString.removeEnd(',') + ' FROM Account';

if(stillNeedsToAddToQuery) // add WHERE, LIMIT, etc. stuff if need be
    // stuff

list<Account> accountList = (list<Account>)database.query(queryString); 
// database.query() returns  list<sObject>, so I like to cast my result

See my answer here for some Utility Methods + Test Code: Can a SOQL query selecting all columns be generated at runtime?


Update

Both @dphil and my answers are equivalent but opposite in a sense when you are dealing with "general" query results:

  • You either filter the input fields for the query (My method gives you all of the fields, and then you can create another method to filter for the appropriate situation.)
  • try/catch whatever the "general" query result is. (And there are clever things that can be done in the catch part too such as break the loop, write another query adding the missing field, and try again with the re-queried results.)
5
  • 1
    My problem is that I don't want every field. I only want the fields I specifically query for for a reason.
    – dphil
    Commented Apr 24, 2014 at 15:22
  • then yea, "try"/"catch" is the only way to go. you can get creative with either your method or my method to get elegant results. Commented Apr 24, 2014 at 21:12
  • check out my update :) Commented Apr 24, 2014 at 21:20
  • The thing is that your answer actually does the opposite of what I need. I did not give the entire picture, only a piece that shows a similar case of how it is being used. It doesn't explain the why because it is not important for the answer. The answers actually aren't equivalent because of the bigger picture that I did not give you.
    – dphil
    Commented Apr 24, 2014 at 21:38
  • I already have the query, and so building it dynamically doesn't help me any. The answers actually aren't equivalent because the end result is very different.
    – dphil
    Commented Apr 24, 2014 at 21:45
0

One way to do this would be to convert the sobject to JSON and use the parser.

Contact myContact = [SeLect Id, Name FROM Contact LIMIT 1];
String contactJson = JSON.serialize(myContact);
JSONParser parser = JSON.createParser(contactJson);

Set<String> queriedFields = new Set<String>();

JSONToken token = parser.nextToken();
token = parser.nextToken(); 
while(parser.hasCurrentToken() ){
  String text = parser.getText();
  if(JSONToken.START_OBJECT == token){
    parser.skipChildren();
    token = parser.nextToken();
  }
  if('attributes' != text && JSONToken.FIELD_NAME == token)
      queriedFields.add(parser.getText());

   token = parser.nextToken();
}

for(String field : queriedFields){
    System.debug(field);
}

You must log in to answer this question.

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