0

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
            }
        },
....}]
}
  • Can you dump the actual value of http_response here? Seems that JSON string in wrong indeed. – Eduard Aug 10 '18 at 14:04
  • 1
    What does the JSON content look like? Most likely there's another layer wrapping the content you want. ({ "response": [ ... content ...] }) – David Reed Aug 10 '18 at 14:04
  • It's hard to know whether your code or the JSON is at fault without seeing the JSON itself. Please edit your question to include the JSON. – Derek F Aug 10 '18 at 14:06
  • As requested, see above – xorLogic Aug 10 '18 at 14:13
7

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.

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.