0

I found this example on a dynamic hierarchy for Accounts and I need help as to how to modify it to display an account hierarchy. I am unable to figure out why I recieve this error message when testing out my link and would like someone to inform me on what to add or change for my goal.

Error message:

Unable to serialize a map with a null key.

Apex Controller:

public class DynamicHierarchyController {
    public String objectApiName {get;set;}
    public String fieldApiName {get;set;}
    public String nameField {get;set;}
    public String currentsObjectId {get;set;}
    public String topParentId {get;set;}
    public String jsonMapsObjectString {get;set;}
    private String jsonString;
    Map<string, set<id>> sObjectIdMap = new Map<string, set<id>>();
    Map<string, SObject> selectedsObjectMap = new Map<string, SObject>();
    Map<id, sObject> allsObjectMap = new Map<id, sObject>();

    public DynamicHierarchyController() 
    {
        currentsObjectId = Apexpages.currentPage().getParameters().get('id');   
    }

    public String getjsonMapString()
    {
        retrieveInfo();
        return jsonString;
    }

    public void retrieveInfo()
    {

    String dynamicQuery = 'SELECT Id, ParentId, Parent_Account_for_LAM__c, Parent.Name, LAM_Shipping_Address__c, Name, Type, OPCO__c, LAM_Account_Owner__c, Rolling_12_Month_Total_Usage_kWh__c, Rolling_12_Month_Total_Revenue__c, Account_Status__c  FROM  Account LIMIT 50000';
       // List <Account>  dynamicQuery = [SELECT ID, ParentId, Parent_Account_for_LAM__c, Parent.Name, LAM_Shipping_Address__c, Name, Type, OPCO__c, LAM_Account_Owner__c, Rolling_12_Month_Total_Usage_kWh__c, 
                               //Rolling_12_Month_Total_Revenue__c, Account_Status__c FROM Account ORDER BY ParentId LIMIT 50000];

        for(sObject obj: Database.query(dynamicQuery))
        {
            allsObjectMap.put(obj.id,obj);

        }

        if(currentsObjectId != null)
        {

            List<SObject> objList = new List<SObject>();
            String dQuery = 'SELECT ID FROM ' + objectApiName + ' WHERE id =\'' + currentsObjectId +'\'';
             objList = Database.query(dQuery);
            currentsObjectId = objList[0].Id;
            retrieveTopParent(currentsObjectId);

                retrieveAllChildRecords(new set<id>{topParentId});
            system.debug(sObjectIdMap.keySet());
            for(String str : sObjectIdMap.keySet())
            {
                selectedsObjectMap.put(str,allsObjectMap.get(str));
            }
            jsonString = JSON.serialize(sObjectIdMap);
            jsonMapsObjectString = JSON.serialize(selectedsObjectMap);
        }

    }

    public void retrieveTopParent(String sObjectId)
    {
        if(allsObjectMap.keySet().contains(sObjectId) && allsObjectMap.get(sObjectId).get(fieldApiName) != null)
        {
            topParentId = String.valueOf(allsObjectMap.get(sObjectId).get(fieldApiName));
            retrieveTopParent(topParentId);
        }
    }

    public void retrieveAllChildRecords(Set<id> sObjectIdSet)
    {
        if(sObjectIdSet.size() > 0)
        { 
            Set<id> allChildsIdSet = new Set<id>();
            for(String str : sObjectIdSet)
            {
                Set<id> childsObjectIdSet = new Set<id>();
                for(sObject obj : allsObjectMap.values())
                {
                    if(obj.get(fieldApiName) != null && String.valueOf(obj.get(fieldApiName)) == str)
                    {
                        childsObjectIdSet.add(obj.Id);
                       allChildsIdSet.add(obj.Id);
                    }
                }
                sObjectIdMap.put(str,childsObjectIdSet);
            }
            retrieveAllChildRecords(allChildsIdSet);
        }
    }



}

Visualfor Component:

  <apex:component controller="DynamicHierarchyController" >
     <apex:attribute name="objectName" description="Name of Object." type="String" required="true" assignTo="{!objectApiName}"/>
     <apex:attribute name="FieldName" description="Name of the field of the object." type="String" required="true" assignTo="{!fieldApiName}"/>
     <apex:attribute name="RepersenterField" description="Name field of the object." type="String" required="true" assignTo="{!nameField}"/>
     <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>

     <div id="parentDiv"></div>

        <style>
         #parentDiv ul:first-child
         {
          padding: 0;
         }
         #parentDiv li
         {
          list-style: none;
          padding: 10px 5px 0 5px;
          position: relative;
         }
      #parentDiv li span 
      {
          -moz-border-radius: 5px;
          -webkit-border-radius: 5px;
          /*border: 1px solid #999;*/
          border-radius: 5px;
          display: inline-block;
          padding: 3px 8px;
          cursor: pointer;
      }
      .selectedRecord
      {
       font-weight:bold; 
       color:blue;
      }
        </style>
        <script>
          var accountMap = JSON.parse('{!jsonMapString}');
          var accountValueMap = JSON.parse('{!jsonMapsobjectString}');
          var cClass = '';
      if("{!topParentId}".indexOf('{!$CurrentPage.parameters.id}') != -1)
       cClass = 'selectedRecord';
      var ul = '<ul><li id="{!topParentId}"  ><span class="' + cClass + '"  onclick="toggleChilds(\'' + '{!topParentId}' + '\',event)" ><b id="i{!topParentId}" class="minus" style="font-size: 1.5em;" >-</b>&nbsp;' +  accountValueMap['{!topParentId}'].{!RepersenterField} + '</span></li></ul>'  ;
      $(ul).appendTo("#parentDiv");
      appendUl('{!topParentId}','{!topParentId}');
          function appendUl(key)
          {
           $.each( accountMap[key], function( index, value ) 
           {
          var dclass = '';
          if(value.indexOf('{!$CurrentPage.parameters.id}') != -1)
           dclass = 'selectedRecord';
          var ul = '<ul class="' + key + '"><li id="' + value + '" ><span class="' + dclass + '" onclick="toggleChilds(\'' + value + '\',event)" ><b id="i' + value + '" class="minus" style="font-size: 1.5em;" >-</b>&nbsp;' + accountValueMap[value].{!RepersenterField} + "</span></li></ul>"  ;
          $(ul).appendTo("#" + key);
          if(value)
           appendUl(value);
       });
          }
          function toggleChilds(key,event)
          {
           $('.'+key).toggle('slow');
           $('#i'+key).toggleClass('minus');
           $('#i'+key).toggleClass('plus');
           if($('#i'+key).hasClass("minus")) 
            $('#i'+key).html("-");
             if($('#i'+key).hasClass("plus")) 
                 $('#i'+key).html("+");
           event.stopPropagation();
          }
        </script>
    </apex:component>

Visualforce Page:

<apex:page standardcontroller="Account" showHeader="true" sidebar="true" >
    <apex:pageblock title="Hierarchy">
        <c:DynamicHierarchyComp objectName="Account" FieldName="ParentId" RepersenterField="Name"/>
    </apex:pageblock>
</apex:page>
3

I can suggest you take a look at the following posts in order to learn a thing or two on troubleshooting your code:

Normally, an error message is also accompanied by a line number. which also comes in handy when troubleshooting.

In this case Unable to serialize a map with a null key. is pretty Verbatim, one of your declared maps has a null key and is raising this error, which one? tbh, i dont know, I'm not going to go through all your code.

Once you do a bit of troubleshooting, you should be able to figure it out, feel free to edit your post once you have done some digging into why the key is null.

quick side note: adding null checks in your code can be a good idea.

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