Get lists of dependent picklist options in Apex

Salesforce doesn't reveal information about dependent picklists in normal Describe calls in Apex, but it is included in calls via the API, and can also be accessed through Apex by serializing and deserializing PicklistEntry objects (see gist linked below for an example of how to do that).

Each PicklistEntry in a dependent field has a property called validFor which contains a Base64 encoded string. When decoded to bits, each bit read left to right corresponds to an option in the controlling field. For example, if you have a validFor of "gAAA"

example pke.validFor: g      A      A      A
displayed as bits:    100000 000000 000000 000000
rearranged as bytes:  10000000 00000000 00000000

As such, you can use loop through all of the picklist values and use bitwise operators to check whether each dependent value is valid for each controlling value.

I wrote a javascript function and Apex Class to abstract all this, which is available as a gist. You can use it like this (assumes you've correctedly loaded the Ajax toolkit in a visualforce page):

/* Build an Object in which keys are valid options for the controlling field
 * and values are lists of valid options for the dependent field.
 */
var OBJ_NAME = 'Custom_Object__c';
var CTRL_FIELD_NAME = "Controlling_Field__c";
var DEP_FIELD_NAME = "Dependent_Field__c";
var options = getDependentOptions(OBJ_NAME, CTRL_FIELD_NAME, DEP_FIELD_NAME);
console.debug(options);

So, this awesome dude, wrote exactly what you were looking for. Might as well pimp his code and spread the word. This was a life save for something I was working on this week!

http://titancronus.com/blog/2014/05/01/salesforce-acquiring-dependent-picklists-in-apex/


Approaches had been well discussed in the above thread. Following is an apex utility function that provides the controlling field value and its dependent field values provided object name, controlling field and dependent field.

//By SharSolutions
   public class MyPickListInfo
   {
        public String validFor;
   }

public static Map<String, List<String>> getFieldDependencies(String objectName, String controllingField, String dependentField)
{
    Map<String, List<String>> controllingInfo = new Map<String, List<String>>();

    Schema.SObjectType objType = Schema.getGlobalDescribe().get(objectName);

    Schema.DescribeSObjectResult describeResult = objType.getDescribe();
    Schema.DescribeFieldResult controllingFieldInfo = describeResult.fields.getMap().get(controllingField).getDescribe();
    Schema.DescribeFieldResult dependentFieldInfo = describeResult.fields.getMap().get(dependentField).getDescribe();

    List<Schema.PicklistEntry> controllingValues = controllingFieldInfo.getPicklistValues();
    List<Schema.PicklistEntry> dependentValues = dependentFieldInfo.getPicklistValues();

    for(Schema.PicklistEntry currControllingValue : controllingValues)
    {
        System.debug('ControllingField: Label:' + currControllingValue.getLabel());
        controllingInfo.put(currControllingValue.getLabel(), new List<String>());
    }

    for(Schema.PicklistEntry currDependentValue : dependentValues)
    {
        String jsonString = JSON.serialize(currDependentValue);

        MyPickListInfo info = (MyPickListInfo) JSON.deserialize(jsonString, MyPickListInfo.class);

        String hexString = EncodingUtil.convertToHex(EncodingUtil.base64Decode(info.validFor)).toUpperCase();

        System.debug('DependentField: Label:' + currDependentValue.getLabel() + ' ValidForInHex:' + hexString + ' JsonString:' + jsonString);

        Integer baseCount = 0;

        for(Integer curr : hexString.getChars())
        {
            Integer val = 0;

            if(curr >= 65)
            {
                val = curr - 65 + 10;
            }
            else
            {
                val = curr - 48;
            }

            if((val & 8) == 8)
            {
                System.debug('Dependent Field: ' + currDependentValue.getLabel() + ' Partof ControllingField:' + controllingValues[baseCount + 0].getLabel());
                controllingInfo.get(controllingValues[baseCount + 0].getLabel()).add(currDependentValue.getLabel());
            }
            if((val & 4) == 4)
            {
                System.debug('Dependent Field: ' + currDependentValue.getLabel() + ' Partof ControllingField:' + controllingValues[baseCount + 1].getLabel());
                controllingInfo.get(controllingValues[baseCount + 1].getLabel()).add(currDependentValue.getLabel());                    
            }
            if((val & 2) == 2)
            {
                System.debug('Dependent Field: ' + currDependentValue.getLabel() + ' Partof ControllingField:' + controllingValues[baseCount + 2].getLabel());
                controllingInfo.get(controllingValues[baseCount + 2].getLabel()).add(currDependentValue.getLabel());                    
            }
            if((val & 1) == 1)
            {
                System.debug('Dependent Field: ' + currDependentValue.getLabel() + ' Partof ControllingField:' + controllingValues[baseCount + 3].getLabel());
                controllingInfo.get(controllingValues[baseCount + 3].getLabel()).add(currDependentValue.getLabel());                    
            }

            baseCount += 4;
        }            
    } 

    System.debug('ControllingInfo: ' + controllingInfo);

    return controllingInfo;
}