0

I am trying to dynamically deserialize a jsonstring (fieldmaplevels wil also be in custom metadata settings) but get the error:

Error: Invalid conversion from runtime type List to Map<String,ANY>

this is at line:

Map<String, Object> fieldMapLevel_0 = (Map<String, Object>)fieldMap.get('Accts');

I also tried:

 Map<String, Object> fieldMapLevel_0 = new Map<String, Object>(fieldMap.get('Accts'));

But get : expected a Map with the same key and value types, or a valid SObject List

Apex

public  with sharing class DynamicJSON{
    public Map<String, Object> fieldMap;
    public static void DynamicJSONmethod()
    {
        sObject newSobject;
        List<sObject> sObjectList;  
        String jsonPayLoad = '{"Accts":[{"Name":"ABC","Exp":25,"Languages":[{"Name":"Apex","version": []},{"Name":"Java","versions":[{"version":1.8,"certification":true,"placeholder":{"target":"reached"}}]}]}]}';
        Map<String, Object> fieldMap = (Map<String, Object>)JSON.deserializeUntyped(jsonPayLoad);
        List<Data_Maps__mdt> mappings = [SELECT QualifiedApiName, label, Object__c , JSON_Object__c,sObjectApiNameLevel_0__c,  sObjectApiNameLevel_1__c,sObjectApiNameLevel_2__c,sObjectApiNameLevel_3__c,
                                         sObjectApiNameLevel_4__c FROM Data_Maps__mdt];
        //level-0
        if(mappings[0].sObjectApiNameLevel_0__c != null) {   
            sobject newSobjLevel_0 = (sObject)Type.forName('Schema',mappings[0].sObjectApiNameLevel_0__c).newInstance();//Account  
            Map<String, Object> fieldMapLevel_0 = (Map<String, Object>)fieldMap.get('Accts');
            GetSobjectFields(newSobjLevel_0, fieldMapLevel_0);
            //level-1
            if(mappings[1].sObjectApiNameLevel_1__c != null) { 
                sobject newSobjLevel_1 = (sObject)Type.forName('Schema',mappings[1].sObjectApiNameLevel_1__c).newInstance();//Languages__c 
                Map<String, Object> fieldMapLevel_1 = (Map<String, Object>)fieldMap.get('Languages');
                GetSobjectFields(newSobjLevel_1, fieldMapLevel_1);
                //level-2
                if(mappings[2].sObjectApiNameLevel_2__c != null) { 
                    sobject newSobjLevel_2 = (sObject)Type.forName('Schema',mappings[0].sObjectApiNameLevel_2__c).newInstance();//versions__c 
                    Map<String, Object> fieldMapLevel_2 = (Map<String, Object>)fieldMap.get('versions');
                    GetSobjectFields(newSobjLevel_2, fieldMapLevel_2);
                    //level-3
                    if(mappings[3].sObjectApiNameLevel_3__c != null) { 
                        sobject newSobjLevel_3 = (sObject)Type.forName('Schema',mappings[0].sObjectApiNameLevel_3__c).newInstance();//placeholder__c 
                        Map<String, Object> fieldMapLevel_3 = (Map<String, Object>)fieldMap.get('placeholder');
                        GetSobjectFields(newSobjLevel_3, fieldMapLevel_3);
                        //level-4
                        if(mappings[4].sObjectApiNameLevel_4__c != null) { 
                            sobject newSobjLevel_4 = (sObject)Type.forName('Schema',mappings[4].sObjectApiNameLevel_4__c).newInstance();//target__c 
                            Map<String, Object> fieldMapLevel_4 = (Map<String, Object>)fieldMap.get('target');
                            GetSobjectFields(newSobjLevel_4, fieldMapLevel_4);                                
                        }
                    }
                }
            }
        }  
    }
    public static sobject GetSobjectFields(sObject newSobj, Map<String,Object> fieldMap ){
        Map<String,String> fieldsMap = new Map<String,String>();
        Map<String, Schema.sObjectField> targetFields = newSobj.getSObjectType().getDescribe().fields.getMap();
        system.debug('[UploadDocuments]targetFields: ' + targetFields);
        for (String key : fieldMap.keySet()) {
            Object value = fieldMap.get(key);
            value = value == ''? null: value;
            switch on targetFields.get(key)?.getDescribe().getType() {
                when DATE {
                    value = Date.valueOf((String)value);
                }
                when DATETIME {
                    value = DateTime.valueOf((String)value);
                }
                when PERCENT, CURRENCY {
                    value = (Decimal)value;
                }
                when DOUBLE {
                    value = Double.valueOf(value);
                }
                when INTEGER {
                    value = (Integer)value;
                }
                when BASE64 {
                    value = Blob.valueOf((String)value);
                }
            }
            newSobj.put(fieldsMap.get(key), value);
        } 
        insert newSobj; 
        system.debug('[DynamicJSON]newSobj: ' + newSobj);
        return newSobj;
    }  
}
7
  • Have you tried List<Object> fieldMapLevel_0 = fieldMap.get('Accts'); ?
    – Nick C
    Commented Jan 24, 2021 at 22:26
  • @NickCook my class GetSobjectFields(sObject newSobj, Map<String,Object> fieldMap ) is expecting a map.
    – Thomas
    Commented Jan 24, 2021 at 22:29
  • 1
    Your JSON doesn't contain a map for the key Accts. It contains a list. Either your code is incorrect or your JSON is incorrect, but the nature of the error is unambiguous.
    – David Reed
    Commented Jan 24, 2021 at 22:34
  • @Thomas Just because your method expects a map does not mean a list of objects must be a map
    – Nick C
    Commented Jan 24, 2021 at 22:36
  • @Thomas, JSON deserialization (untyped) turns JSON objects to Map<String, Object> and JSON arrays into List<Object>. Since the JSON has 'Accts' as an array, this means you get a List and that is how you must process it.
    – Phil W
    Commented Jan 24, 2021 at 22:37

1 Answer 1

2
Map<String, Object> fieldMapLevel_0 = (Map<String, Object>)fieldMap.get('Accts');

The value of the key Accts in your JSON is a List, not a Map:

    String jsonPayLoad = '{"Accts":[{"Name":"ABC","Exp":25,"Languages":[{"Name":"Apex","version": []},{"Name":"Java","versions":[{"version":1.8,"certification":true,"placeholder":{"target":"reached"}}]}]}]}';

The runtime type is List<Object>.

This syntax

Map<String, Object> fieldMapLevel_0 = new Map<String, Object>(fieldMap.get('Accts'));

only works on lists of sObjects to create a Map keyed on the Id field; your data does not have Ids present and it's not clear what the unique identifier is, if any. You'd have to iterate to create a Map from this List, but if the key you select from your data is not unique, you'll have to be prepared to handle that in a way appropriate to your business requirements.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .