function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Eric Blaxton 11Eric Blaxton 11 

APEX callout HTTPRequest error

Hi and thanks for any tips in advance.
First time writing a Get request. 

1. My Class:
public class MaintenanceTicket 
{
	public static String getMaintenanceTickets(string location )
    {
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();     
                    
        req.setEndpoint('https://api.fake/odata/AccountBalances?$expand=businessUnit&$count=true&$skip=0&$top=3');
      
        req.setTimeout(120000);    
            
        req.setMethod('GET');
       
       // QA Authorization
       req.setHeader('Authorization', 'Bearer ' + 'FakeID');
        HTTPResponse res = h.send(req);
        String strResponse = res.getBody();
        
        if(res.getstatusCode() == 200 && res.getbody() != null)
            system.debug('Response: ' + res.getBody());
        {
         //MAP<String,Object> jsonBody = (Map<String,Object>)Json.deserializeUntyped(res.getBody()); // pass data
        
         List<Object > jsonBody = (List<Object>) Json.deserialize(strResponse, List<Object>.class);
          
         system.debug('Got these values:');
         
         System.debug(jsonBody);
        
        String ticket = String.valueof(jsonBody);
                
        return ticket;
        
        }
                  
     } 
}
2. My Remote Site settings is accurate

3. My anonymous apex code:
String busloc = MaintenanceTicket.getMaintenanceTickets('385');
    System.debug(busloc);

4. Response body (system.debug):
13:10:22:633 USER_DEBUG [26]|DEBUG|Response: {"@odata.context":"http://api.fake/$metadata#AccountBalances(businessUnit())",
"@odata.count":xxx,
"value":[{"id":1,
"businessUnitId":xxx,
"charges":46536.710000,
"credits":-37741.810000,
"balance":8794.900000,
"effectiveDate":"2020-03-03T02:54:03.81-06:00",
"businessUnit":{"id":385,"transactionType":2,"billToNumber":&quot

5.  The error:
13:10:22:654 FATAL_ERROR System.JSONException: Malformed JSON: Expected '[' at the beginning of List/Set

13:10:22:000 FATAL_ERROR Class.System.JSON.deserialize: line 15, column 1

13:10:22:000 FATAL_ERROR Class.MaintenanceTicket.getMaintenanceTickets: line 30, column 1

Regards,
Eric
​​​​​​​

 
Best Answer chosen by Eric Blaxton 11
Daniel AhlDaniel Ahl

Hello Eric, 

So the issue seems to be that since you are trying to deserialize the JSON into a List<>, which should start with an '[', it fails, since your response: strResponse is starting with an "{" => {"@odata.context"

If you would have taken only the value (shown below) from the object 

[{"id":1,\n'+
    '"businessUnitId":xxx,\n'+
    '"charges":46536.710000,\n'+
    '"credits":-37741.810000,\n'+
    '"balance":8794.900000,\n'+
    '"effectiveDate":"2020-03-03T02:54:03.81-06:00"}]
List<Object> isn't an JSON supported Apex type, so it would have failed, giving you another error.

Also values like below would fail, since xxx would have to be a string still even the deserialization of the JSON (or a number).

"@odata.count":xxx

I am guessing that you want the information within the "value" property of the response so I would probably do something like this:

MAP<String,Object> jsonBody = (Map<String,Object>)Json.deserializeUntyped(strResponse);
Object value = jsonBody.get('value');
String ticket = String.valueof(value);
return ticket;
 

 

All Answers

AbhishekAbhishek (Salesforce Developers) 
https://salesforce.stackexchange.com/questions/227814/fatal-error-system-jsonexception-malformed-json-expected-at-the-beginning

Check this once.
Eric Blaxton 11Eric Blaxton 11
Hello Abhishek,  

I've read this.  What point are you trying to make?

Eric
Daniel AhlDaniel Ahl

Hello Eric, 

So the issue seems to be that since you are trying to deserialize the JSON into a List<>, which should start with an '[', it fails, since your response: strResponse is starting with an "{" => {"@odata.context"

If you would have taken only the value (shown below) from the object 

[{"id":1,\n'+
    '"businessUnitId":xxx,\n'+
    '"charges":46536.710000,\n'+
    '"credits":-37741.810000,\n'+
    '"balance":8794.900000,\n'+
    '"effectiveDate":"2020-03-03T02:54:03.81-06:00"}]
List<Object> isn't an JSON supported Apex type, so it would have failed, giving you another error.

Also values like below would fail, since xxx would have to be a string still even the deserialization of the JSON (or a number).

"@odata.count":xxx

I am guessing that you want the information within the "value" property of the response so I would probably do something like this:

MAP<String,Object> jsonBody = (Map<String,Object>)Json.deserializeUntyped(strResponse);
Object value = jsonBody.get('value');
String ticket = String.valueof(value);
return ticket;
 

 

This was selected as the best answer
AbhishekAbhishek (Salesforce Developers) 
Eric In that discussion they are mentioning ways to over the errors like showing the above.
Eric Blaxton 11Eric Blaxton 11
Appreciate both of your help.  Here's the code changes I made.  It works, now I need to figure out what to do with it.  :)
 
public class MaintenanceTicket 
{
	public static String getMaintenanceTickets(string businessUnitId )
    {
        HTTP h = new HTTP();
        HTTPRequest req = new HTTPRequest();
        
        req.setEndpoint('https://fakepath/odata/AccountBalances?$expand=businessUnit&$count=true&$skip=0&$top=3');
      
        req.setTimeout(120000);       
        req.setMethod('GET');
        
        // QA Authorization
        req.setHeader('Authorization', 'Bearer ' + 'fake path');
        
        HTTPResponse res = h.send(req);
        String strResponse = res.getBody();
        system.debug('Response: ' + res.getBody());
        
        if(res.getstatusCode() == 200 && res.getbody() != null)
            system.debug('Response: ' + res.getBody());
        {        
                    
         Map<String,Object> newMap = (Map<String, Object>)JSON.deserializeUntyped(strResponse);
                   
         System.debug('Got these values:' + newMap);
         
            List<Object > valuelist = (List<Object>) newMap.get('value'); 
            System.debug(valuelist);
            for (Object obj : valuelist )
            {
                Map<String,Object> valueMap = (Map<String, Object> )obj;
                string id= String.valueOf(valueMap.get('id'));
                string businessUnit= String.valueOf(valueMap.get('businessUnitId'));
                System.debug(id);
                System.debug(businessUnit);
                Map<String,Object> busunitmap  = (Map<String, Object>)valueMap.get('businessUnit');
                string divnum= String.valueOf(busunitmap.get('divisionNumber'));
                System.debug(divnum);
            }
            
         return null;
        
        }
                  
     } 
}