1

I'm trying to write a method for working with sObject.put(field, value) statements in a loop where the Schema.DisplayType of the fields received varies.

The goal is to have the method return the name of a compatible DisplayType you can convert the value to in order to have it assign properly without breaking the statement. Although I could figure this out by trial and error, I was wondering if anyone knew (off the top of their head) or could direct me to (since I haven't been able to find it online) a list of compatible types. As an example, in my method below, I've grouped String, TextArea, Id, Picklist, Reference, Phone, Email and URL together because if you pass a string to fields of any of these fields, it will accept the value, but I'm wondering if I can get away with further grouping. E.g. could I put Boolean in that list too, or are some of the Boolean field values 0 and 1, and passing a string would be problematic? Or if I pass an Integer field a Decimal value, will it just truncate it, or will an error be thrown?

/** SCHEMA DISPLAY TYPE COMPATIBILITY
 * @param field <Scehma.SObjectField
 * @return <String>
 **/
public static String schemaDisplayTypeCompatibility(Schema.SObjectField field){
    DescribeFieldResult fielddesc = field.getDescribe();
    DisplayType fieldType = fielddesc.getType();
    Boolean canUpdate = fielddesc.isUpdateable();

    if(canUpdate == FALSE)
        return 'NOT UPDATEABLE';    
    if(fieldType == Schema.DisplayType.String || 
        fieldType == Schema.DisplayType.TextArea ||
        fieldType == Schema.DisplayType.Id ||
        fieldType == Schema.DisplayType.Picklist ||
        fieldType == Schema.DisplayType.Reference ||
        fieldType == Schema.DisplayType.Phone ||
        fieldType == Schema.DisplayType.Email ||
        fieldType == Schema.DisplayType.URL)
            return 'String';
    if(fieldType == Schema.DisplayType.Currency ||
       fieldType == Schema.DisplayType.Double)
        return 'Decimal';
    if(fieldType == Schema.DisplayType.Integer)
        return 'Integer';
    if(fieldType == Schema.DisplayType.Boolean)
        return 'Boolean';
    if(fieldType == Schema.DisplayType.DateTime)
        return 'DateTime';    
    if(fieldType == Schema.DisplayType.Date)
        return 'Date';            
    if(fieldType == Schema.DisplayType.Time)
        return 'Time';
    if(fieldType == Schema.DisplayType.Combobox)
        return 'Combobox';    
    if(fieldType == Schema.DisplayType.MultiPicklist)
        return 'MultiPicklist';
   if(fieldType == Schema.DisplayType.EncryptedString)
        return 'EncryptedString';
   if(fieldType == Schema.DisplayType.DataCategoryGroupReference)
        return 'DataCategoryGroupReference';        
   if(fieldType == Schema.DisplayType.base64 )
        return 'base64 ';               
   //if(fieldType == Schema.DisplayType.anytype)
   //     return 'anytype';                                  
    return 'UNKNOWN';    
}
4
  • 2
    The getSOAPType() enum values look closer to the core Apex types at first sight; returning that enum value and type converting based on it might be a simpler way to go. Boolean is an explicit type in Apex.
    – Keith C
    Feb 11 '16 at 21:59
  • Is this still an open question?
    – Adrian Larson
    Mar 7 '16 at 14:44
  • Sorry Adrian! I thought I already marked your response as answering my question.
    – KB145
    Mar 8 '16 at 20:16
  • Np just wasn't sure if you wanted any more detail. I finally did implement it myself recently. Cheers!
    – Adrian Larson
    Mar 8 '16 at 20:59
4

As @KeithC mentions, Schema.SoapType is much simpler to work with.

Disclaimers

Maybe there's a simpler way than what I outline below. I didn't see the project through to completion so I can't guarantee it will be worth the effort to implement. I am also unsure of where you are pulling your inputs from. Also you may want to handle null values, but I ommitted such logic for simplicty's sake.

Anyway, the way I've done this in the past is to map SoapType to a Type of converter.

public with sharing class PutReference
{
    final SObjectField field;
    final IConverter converter;
    public PutReference(SObjectField field)
    {
        this.field = field;
        SoapType soapType = field.getDescribe().getSoapType();
        this.converter = converters.get(soapType).newInstance();
    }
    public SObject putTo(SObject record, String input)
    {
        record.put(field, converter.getValue(input));
    }

    static final Map<SoapType, Type> converters = new Map<SoapType, Type>();
    {
        SoapType.DOUBLE, DoubleConverter.class
        // SoapType.DATE, DateConverter.class
        // etc
    }
    public interface IConverter { Object getValue(String input); }
    public class DoubleConverter implements IConverter
    {
        Object getValue(String input)
        {
            return Double.valueOf(input);
        }
    }
    // public class DateConverter
    // etc.
}

A bonus of this approach is that you could get more sophisticated with your conversion logic. For example:

public class BooleanConverter implements IConverter
{
    public Object getValue(String input)
    {
        if (input == '0') return false;
        if (input == '1') return true;
        return Boolean.valueOf(input);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.