[SalesForce] Unexpected character (‘a’ (code 97)): expected a valid value (number, String, array, object, ‘true’, ‘false’ or ‘null’) at input location [1,2]

I have a batch class which makes a call out to an api within the same org (the rest resource was developed by a 3rd party supplier and I cannot see its source code)

Anyway, as per the supplier the json that it accepts is below (I have tested it in workbench and it returns 200 status code)

 [{
  "CIPHR_Id" : "8693_54808",
  "hours" : 7.40,
  "date" : "2010-02-08",
  "activity" : "a5z1w0000004CH5AAM",
  "resource" : "10294"
}, {
  "CIPHR_Id" : "8693_54809",
  "hours" : 7.40,
  "date" : "2010-02-09",
  "activity" : "a5z1w0000004CH5AAM",
  "resource" : "10294"
}]

My code is below (sorry had to paste only relevant bits):

//Prepare the payload
    for(Ciphr.AbsenceDetail cad: CADMap.Values()){
        Map<String,Object> MaptoSerialize = new Map<String,Object>{'resource' => cad.employeeNumber,'activity' => 'a5z1w0000004CH5AAM', 'date' => Date.valueOf(cad.start), 'hours' => cad.Hours, 'CIPHR_Id' => cad.ID};
        PayLoad.add(MaptoSerialize);
    }    

    String responseOfPayloadPush = SendPayload(PayLoad);
System.debug('*******************Payload******************\n'+json.serializePretty(PayLoad));
}
private String SendPayload(List<Map<String,Object>> payload){
    String sfdcURL = URL.getSalesforceBaseUrl().toExternalForm(); 
    String restAPIURL = sfdcURL + '/services/apexrest/****/****/***/***';  

    HttpRequest httpRequest = new HttpRequest();
    httpRequest.setEndpoint(restAPIURL); 
    httpRequest.setMethod('POST'); 
    httprequest.setHeader('Content-Type', 'application/json');
    httprequest.setHeader('Accept','application/json');
    httpRequest.setHeader('Authorization', 'OAuth ' + UserInfo.getSessionId());        
    httpRequest.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());  
    httpRequest.setBody(json.serializePretty(PayLoad));
    String response = '';
    try {  
        Http http = new Http();   
        HttpResponse httpResponse = http.send(httpRequest);  
        response = JSON.serializePretty( JSON.deserializeUntyped(httpResponse.getBody()) );
    } catch(Exception e) {  
        System.debug('ERROR: '+ e.getMessage());  
        response = e.getMessage();
        sendEmail('Payload Sending to Kimble failed','Exception Occurred Payload Push',e.getMessage(),true,restAPIURL);
    }  
    System.debug(' ** response ** : ' + response );
    return response;
}
private void sendEmail(string displayName, string subject, String messageBody, boolean exceptionOccurred, String endpoint){
    Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
    mail.setToAddresses(new String[] {'*****@****.net'});
    mail.setReplyTo('batch@acme.com');
    mail.setSenderDisplayName(displayName);
    mail.setSubject(subject);
    if(exceptionOccurred){
        mail.setPlainTextBody('Exception: '+messageBody+'\n\nFor URL: '+endpoint);
    }else{
        mail.setPlainTextBody(messageBody);
    } 
    Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}

My debug displays the correct json string as showed above but I get the error
Unexpected character ('a' (code 97)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at input location [1,2]

Could someone please help me? I cannot comprehend as to what am I missing perhaps something obvious since the debug I get as a valid json string (checked in JSLint) and exactly as the one that works from workbench!

Best Answer

While your code may be POSTing valid JSON to the API, this code that aims to parse the response:

Http http = new Http();   
HttpResponse httpResponse = http.send(httpRequest);  
response = JSON.serializePretty( JSON.deserializeUntyped(httpResponse.getBody()));

assumes that the response body is JSON and based on the error message it isn't. I suggest you add debug logging and find out what what is coming back before the deserialize call:

Http http = new Http();   
HttpResponse httpResponse = http.send(httpRequest);  
System.debug('>>> response ' + httpResponse.getBody());
response = JSON.serializePretty( JSON.deserializeUntyped(httpResponse.getBody()));

and change your code to match.

It is also a good idea to look at the status code in the response in the production code as just because the service works with one sample input does not mean it will work with other input or 100% of the time. See the