[SalesForce] Not sure why I can’t deserialize an HTTP JSON object response

I'm trying to figure out what I'm doing wrong here. I'm trying to quickly deserialize HTTP JSON output into a string to search thru and pull specific keys to see if they meet a certain condition. My code doesn't come back with any errors, but when I go to execute it, I receive the following notice:

Execute Anonymous Error
Line: 15, Column: 1 System.JSONException: Malformed JSON: Expected '[' at the beginning of List/Set

My Apex code is as follows:

public static List<String> listGroups(){ 
    HTTPRequest request = new HttpRequest();
    request.setMethod('GET');
    request.setHeader('Accept', 'application/json');
    request.setEndpoint('callout:Website1/');
    HTTPResponse response = new Http().send(request);
    String http_response = response.getBody();
    List<String> data = (List<String>) JSON.deserialize(http_response, List<String>.class);
    return data;
}

And here is the function call I'm performing elsewhere in my Apex program:

List<String> output=listGroups();

JSON output example:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')/drive/root/children",
    "value": [
        {
            "createdDateTime": "2018-06-04T20:30:42Z",
            "eTag": "\"{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},1\"",
            "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "lastModifiedDateTime": "2018-06-04T20:30:42Z",
            "name": "Jack's files",
            "webUrl": "https://example.com/sites/xxxxx/",
            "cTag": "\"c:{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx},0\"",
            "size": 6566266651,
            "createdBy": {
                "user": {
                    "email": "MBravo@example.com",
                    "id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
                    "displayName": "Mike Bravo"
                }
            },
            "lastModifiedBy": {
                "user": {
                    "email": "MBravo@example.com",
                    "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxx",
                    "displayName": "Mike Bravo"
                }
            },
            "parentReference": {
                "driveId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "driveType": "documentLibrary",
                "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "path": "/drive/root:"
            },
            "fileSystemInfo": {
                "createdDateTime": "2018-06-04T20:30:42Z",
                "lastModifiedDateTime": "2018-06-04T20:30:42Z"
            },
            "folder": {
                "childCount": 1
            }
        },
....}]
}

Best Answer

By passing List<String>.class to the JSON.deserialize function, you're telling it to look for a list. A list in JSON should start with [. The error message is telling you that it looked for [, but couldn't find it.

Check exactly what the web service is returning by outputting http_response to the debug log.

Some services return a single object instead of a list with one item if there's only one item. Which is annoying, but can be handled if you're looking for it.

Edit

Now that you've elaborated on what you're trying to do, I'd say you need to parse the whole thing using the untyped parser like this:

Map<String, Object> topLevel = (Map<String, Object>)JSON.deserializeUntyped(http_response);
List<Object> values = (List<Object>)topLevel.get('value');
System.debug(values);

I know you said you don't need to parse all of it, but this is by far the most concise approach. I guess you could serialise back to JSON again once you've found the right part of the tree. But, TBH, text-searching JSON doesn't sound like a great idea in the first place.

Related Topic