[SalesForce] Create JSON from Picklist Entries with both Controller and Dependent Picklist

Am having JQuery auto complete search box in visualforce page. Currently the input for this search box is(ajax data) JSON. Which is a static resource file. But If client add one more option in the picklist field then they can't able find that option in the auto complete search box. So, I want to make it as dynamic. So decided to get the values in apex and form a JSON and pass the JSON data from apex to ajax call.

Picklist Field Names

  1. Technology – Controlling picklist

  2. Sub Technology – Dependent Picklist

Currently my static resource JSON file is looking like this(sample),

[  
   {  
      "techarea":"Dotnet",
      "subtecharea":"Csharp",
      "keywords":"",
      "label":"Dotnet => Csharp => "
   },
   {  
      "techarea":"Dotnet",
      "subtecharea":"ASP",
      "keywords":"",
      "label":"Dotnet => ASP => "
   },
   {  
      "techarea":"JAVA",
      "subtecharea":"JSP",
      "keywords":"",
      "label":"JAVA => JSP => "
   }
]

Am trying with Schema Picklist Entries method but can't able to build with controller and dependent format.
Really appreciable if anyone help me to achieve this.

Updated:

Sample Class Am trying to build

public class CreateJSONFromPicklists {

public void createFromCaseTATSAPicklists(){
    Schema.DescribeFieldResult TAfieldResult = Case.Technology_Area__c.getDescribe();
    Schema.DescribeFieldResult TSAfieldResult = Case.Sub_Technology_Area__c.getDescribe();

    List<Schema.PicklistEntry> TAple = TSAfieldResult.getPicklistValues();
    List<Schema.PicklistEntry> TSAple = TSAfieldResult.getPicklistValues();

    Transient String buildJSON = '';
    for( Schema.PicklistEntry TAf : TAple)
    {
        for(Schema.PicklistEntry TSAf: TSAple){
            // options.add(new SelectOption(f.getLabel(), f.getValue()));
            buildJSON += '{"techarea":'+ TAf.getValue()+',"subtecharea":'+TSAf.getValue()+',"keywords":"","label":"'+TAf.getValue()+' => '+TSAf.getValue()+' => "},';
        }

    }
    system.debug('@@@ BuildJSON @@@ '+buildJSON);
    //return options;
}

}

But apex heap size issue is throwing here. Also doubt on controlling dependent values format.

Best Answer

Thanks for this great gist post https://gist.github.com/boxfoot/4166342

So here is my whole class to build fieldDenpendency JSON data

public class CreateJSONFromPicklists {
public static string getDependentOptionsImpl(Schema.SObjectField theField, Schema.SObjectField ctrlField) {
        // validFor property cannot be accessed via a method or a property,
        // so we need to serialize the PicklistEntry object and then deserialize into a wrapper.
        List<Schema.PicklistEntry> contrEntries = ctrlField.getDescribe().getPicklistValues();
        List<PicklistEntryWrapper> depEntries = CreateJSONFromPicklists.wrapPicklistEntries(theField.getDescribe().getPicklistValues());

        // Set up the return container - Map<ControllingValue, List<DependentValues>>
        Map<String, List<String>> objResults = new Map<String, List<String>>();
        List<String> controllingValues = new List<String>();

        for (Schema.PicklistEntry ple : contrEntries) {
            String label = ple.getLabel();
            objResults.put(label, new List<String>());
            controllingValues.add(label);
        }

        for (PicklistEntryWrapper plew : depEntries) {
            String label = plew.label;
            String validForBits = base64ToBits(plew.validFor);
            for (Integer i = 0; i < validForBits.length(); i++) {
                // For each bit, in order: if it's a 1, add this label to the dependent list for the corresponding controlling value
                String bit = validForBits.mid(i, 1);
                if (bit == '1') {
                    objResults.get(controllingValues.get(i)).add(label);
                }
            }
        }
        string fieldDependencies = '';
        for(string controllervalue : objResults.keySet()){
            if(objResults.get(controllervalue) != null){
                List<String> dependencies = objResults.get(controllervalue);
                for(string dependentValue : dependencies){
                    fieldDependencies+= '{"techarea":"'+controllervalue+'","subtecharea":"'+dependentValue+'","keywords":"","label":"'+controllervalue+' => '+dependentValue+' => "},';
                }

            }
        }
        system.debug('@@@ fieldDependencies @@@ '+fieldDependencies);
        return fieldDependencies;
    }

    // Convert decimal to binary representation (alas, Apex has no native method :-(
    //    eg. 4 => '100', 19 => '10011', etc.
    // Method: Divide by 2 repeatedly until 0. At each step note the remainder (0 or 1).
    // These, in reverse order, are the binary.
    public static String decimalToBinary(Integer val) {
        String bits = '';
        while (val > 0) {
            Integer remainder = Math.mod(val, 2);
            val = Integer.valueOf(Math.floor(val / 2));
            bits = String.valueOf(remainder) + bits;
        }
        return bits;
    }

    // Convert a base64 token into a binary/bits representation
    // e.g. 'gAAA' => '100000000000000000000'
    public static String base64ToBits(String validFor) {
        if (String.isEmpty(validFor)) return '';

        String validForBits = '';

        for (Integer i = 0; i < validFor.length(); i++) {
            String thisChar = validFor.mid(i, 1);
            Integer val = base64Chars.indexOf(thisChar);
            String bits = decimalToBinary(val).leftPad(6, '0');
            validForBits += bits;
        }

        return validForBits;
    }


    private static final String base64Chars = '' +
        'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
        'abcdefghijklmnopqrstuvwxyz' +
        '0123456789+/';


    private static List<PicklistEntryWrapper> wrapPicklistEntries(List<Schema.PicklistEntry> PLEs) {
        return (List<PicklistEntryWrapper>)
            JSON.deserialize(JSON.serialize(PLEs), List<PicklistEntryWrapper>.class);
    }

    public class PicklistEntryWrapper {
        public String active {get; set;}
        public String defaultValue {get; set;}
        public String label {get; set;}
        public String value {get; set;}
        public String validFor {get; set;}
    }
}

Invoking like this,

CreateJSONFromPicklists.getDependentOptionsImpl(Case.Sub_Technology_Area__c, Case.Technology_Area__c);

Related Topic