0

I am trying to deserialize a json string and get the fieldtypes but get an error on the valueType. I am trying to simulate a Json request from postman to send a Post with a list of accounts.

I dont know if my JSON is correct from postman see:

enter image description here

  1. Is my JSON correct?
  2. Why does this result in an NullPointerException?

Apex

   Map<String, Object> fieldMap = (Map<String, Object>)JSON.deserializeUntyped(requestString);
    system.debug('[UploadDocuments]fieldMap: ' + fieldMap); 
    
    SObjectType sobjType = ((SObject)(Type.forName('Schema.' + 'Account').newInstance())).getSObjectType();
    SObject newSobject = sobjType.newSObject();

    Map<String, Schema.sObjectField> targetFields = sobjType.getDescribe().fields.getMap();
    for (String key : fieldMap.keySet())
    {
        Object value = fieldMap.get(key);
        Schema.DisplayType valueType = targetFields.get(key).getDescribe().getType();
        if (value instanceof String && valueType != Schema.DisplayType.String)
        {
            String svalue = (String)value;
            if (valueType == Schema.DisplayType.Date)
                newSobject.put(key, Date.valueOf(svalue));
            else if(valueType == Schema.DisplayType.DateTime)
                newSobject.put(key, DateTime.valueOfGmt(svalue));
            else if (valueType == Schema.DisplayType.Percent || valueType == Schema.DisplayType.Currency)
                newSobject.put(key, svalue == '' ? null : Decimal.valueOf(svalue));
            else if (valueType == Schema.DisplayType.Double)
                newSobject.put(key, svalue == '' ? null : Double.valueOf(svalue));
            else if (valueType == Schema.DisplayType.Integer)
                newSobject.put(key, Integer.valueOf(svalue));
            else if (valueType == Schema.DisplayType.Base64)
                newSobject.put(key, Blob.valueOf(svalue));
            else
                newSobject.put(key, svalue);
        }
        else
            newSobject.put(key, value);
    }
    insert newSobject;
    system.debug('newSobject: ' + newSobject); 

Debug of fieldmap: {Accts=({name=Alice, title=title1}, {name=Ben, title=title2})}

This issue is related to: How to dynamically get name of object JSON String

Thanks in advance.

2
  • Can you give the line of the NPE ?
    – Badbaxx
    Jan 19, 2021 at 10:33
  • @Badbaxx Its the valueType line see: Schema.DisplayType valueType = targetFields.get(key).getDescribe().getType();
    – Thomas
    Jan 19, 2021 at 10:41

1 Answer 1

2

You're missing the part where you get "Accts" and operate on that resource.

Map<String, Object> fieldMap = (Map<String, Object>)JSON.deserializeUntyped(requestString);

Should start off as:

Map<String, Object> topLevelResource = (Map<String, Object>)JSON.deserializeUntyped(requestString);
List<Object> acctsList = (List<Object>)topLevelResource.get('Accts');
Account[] accountsToInsert = new Account[0];
for(Object acctItem: acctsList) {
  Map<String, Object> fieldMap = (Map<String, Object>)acctItem;
  Account thisAccount = new Account(); // Or dynamic, as in your code
  // put fields into thisAccount, and then...
  accountsToInsert.put(thisAccount);
}
insert accountsToInsert; // DML outside of loop is good
6
  • Thanks for your answer. Suppose I dont know Accts beforehand is there a way to extract this from the JSON dynamically?
    – Thomas
    Jan 19, 2021 at 10:43
  • @Thomas Then it's nested loop time: Map<String, Object> topLevelResource = (Map<String, Object>)JSON.deserializeUntyped(requestString); for(String topLevelKey: topLevelResource.keySet()) { List<Object> topLevelRecordList = (List<Object>)topLevelResource.get(topLevelKey); for(Object recordResource: topLevelRecordList) { Map<String, Object> fieldMap = (Map<String, Object>)recordResource; ...
    – sfdcfox
    Jan 19, 2021 at 10:47
  • Thanks. In this way get the map but what I meant is to get the Acct key itself dynamically as a string.
    – Thomas
    Jan 19, 2021 at 11:20
  • @Thomas the topLevelKey in this second example is the key. You could get just the keySet and convert it to a list if you prefer.
    – sfdcfox
    Jan 19, 2021 at 11:25
  • @Thomas nice to see you raising new questions for different issues even though they are related to one over-all solution. It might be nice to add links in subsequent questions back to the originating question as a sort of foot note (at the end of the question)...?
    – Phil W
    Jan 19, 2021 at 11:36

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.