[SalesForce] REST to create multiple objects-JSON Deserializaton failed on token null

I have been trying to create CurrencyType records from APEX and since that doesn't support DML, have been using the REST endpoint and POST method.
Everything work fine with single record but with multiple records, I am getting this error:

[
{
"message": "Json Deserialization failed on token 'null' and has left off in the middle of parsing a row. Will go to end of row to begin parsing the next row",
"errorCode": "INVALID_FIELD"
}
]

I don't see how the code worked for single object, if it really were an Invalid Field.

I have seen this and this but have been unable to fix my issue.

Here is my code:

public static void syncCurrencyTypeTableMultiple(){
    Http h = new Http();
    HttpRequest req = new HttpRequest();
    req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v41.0/sobjects/CurrencyType/');
    req.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());
    req.setHeader('Content-Type', 'application/json');
    req.setMethod('POST');

    List<CurrencyType> currTypeList = new List<CurrencyType>();

    for(sanmgdpack__PST_Currency__c curr: [Select sanmgdpack__ISO_Code__c, sanmgdpack__Conversion_Rate__c, sanmgdpack__Decimal_Places__c FROM sanmgdpack__PST_Currency__c]) {
        CurrencyType currTypeObj = new CurrencyType(
                                            IsoCode = curr.sanmgdpack__ISO_Code__c, 
                                            ConversionRate = curr.sanmgdpack__Conversion_Rate__c, 
                                            DecimalPlaces = Integer.valueOf(curr.sanmgdpack__Decimal_Places__c)
                                            );
        currTypeList.add(currTypeObj);
    }

    String jsonStr = JSON.serializePretty(currTypeList);
    System.debug('json Str:' + jsonStr);


    //test
    //List<CurrencyType> deserList = (List<CurrencyType>)JSON.deserialize(jsonStr, List<CurrencyType>.class);

    //System.debug('deserlist::::' + deserList); //works fine

    req.setBody(jsonStr);
    System.debug(req);
    HttpResponse res = h.send(req);
    System.debug(res);
}

Best Answer

The SFDC REST API for Create-Update-Delete operations only work on single records. To address this, SFDC added a Composite Resource feature that allows:

  • inserting multiple unrelated objects (your use case)
  • inserting a tree of objects (e.g. Account and its child Contacts)
  • inserting an object, then using its values to insert/update another object

and more. See the REST API documentation on Composite resources

For multiple CurrencyType (max 200)

https://yourInstance.salesforce.com/services/data/v41.0/composite/tree/CurrencyType/

with POST body:

{
"records" :[{
    "attributes" : {"type" : "CurrencyType", "referenceId" : "ref11"},
    "IsoCode": "USD",
    "DecimalPlaces": 2,
    "ConversionRate": 1.3   
    },{
    "attributes" : {"type" : "CurrencyType", "referenceId" : "ref22"},
    "IsoCode": "CHF",
    "DecimalPlaces": 2,
    "ConversionRate": 1.5
    },
    ...
   ]
}

The referenceId should be unique and are used to assist you in correlating the REST Response body to see which rows failed to insert.

There is a superb discussion in Daniel Ballinger's blog on bulk updating from an API that is well worth reading

Related Topic