The problem I'm running into is that I have a class that is converting SObjects into JSON and thus needs to iterate over the fields present in the SObject to create a consumable JSON map. The only efficient way I have found to do this is the following:
Map<String, String> resultMap = new Map<String,String>();
// Iterate over all possible fields on the object to find the ones in the sObject passed in
for (String fieldName : Utils.getSObjectFields(sObj.getSObjectType()).keySet()) {
// Passed in object has the field
try {
resultMap.put(fieldName, String.valueOf(sObj.get(fieldName)));
} catch (System.SObjectException except) { /* field not found in sObj*/}
}
public with sharing class Utils {
private static Map<String, Map<String,Schema.Sobjectfield>> sObjectFieldCache =new Map<String, Map<String,Schema.Sobjectfield>>();
public static Map<String,Schema.Sobjectfield> getSObjectFields(Schema.SObjectType sObjectType) {
String sObjectTypeAsString = String.valueOf(sObjectType);
// If it's not already in the cache, add the sObject's field map to the cache
if (!sObjectFieldCache.containsKey(sObjectTypeAsString)) {
sObjectFieldCache.put(sObjectTypeAsString, sObjectType.getDescribe().fields.getMap());
}
return sObjectFieldCache.get(sObjectTypeAsString);
}
}
Unfortunately, this is really slow (presumably because it has to iterate over all possible fields and throws and catches an exception every time a field is encountered that isn't in the sObject). A simple i to check if an SObject has a field instead of having to catch the exception each time. If a "hasField(String fieldName)" method was implemented, I could change the code to:
Map<String, String> resultMap = new Map<String,String>();
// Iterate over all possible fields on the object to find the ones in the sObject passed in
for (String fieldName : Utils.getSObjectFields(sObj.getSObjectType()).keySet()) {
// Passed in object has the field
if (sObj.hasField(fieldName)) {
resultMap.put(fieldName, String.valueOf(sObj.get(fieldName)));
}
}
A preferable alternative, would be to able to iterate over the fields in an SObject so that I wouldn't have to iterate over all possible fields, particularly if the org has hundreds of custom fields. That would allow:
Map<String, String> resultMap = new Map<String,String>();
// Iterate over all possible fields on the object to find the ones in the sObject passed in
for (String fieldName : sObj.getAllFields()) {
// Passed in object has the field
resultMap.put(fieldName, String.valueOf(sObj.get(fieldName)));
}