0

I have a situation where when I make a callout I get a single json response like this:

{
    "Person": {
        "Infomration": {
            "IndividualInformation": {
                "IndividualCode": "XXXXXX",
                "IndividualType": {
                    "Resident": 0,
                    "Alive": "Yes",
                }
            },FamilyInformation": {
                "FamilyCode": 0101010,
                "PresentInFamily": 1
            }
        },
        ..... a really long json reponse
}

Notice that there is only a single {} indicating a single element. The problem is that sometimes the external system can send more than one person depending of the search result of the external system. I was not given a sample array response, but I am assuming it will be with like this:

[{
        "Person": {
            "Infomration": {
                "IndividualInformation": {
                    "IndividualCode": "XXXXXX",
                    "IndividualType": {
                        "Resident": 0,
                        "Alive": "Yes",
                    }
                },FamilyInformation": {
                    "FamilyCode": 0101010,
                    "PresentInFamily": 1
                }
            },
            ..... 
    }, "Person": {
"Infomration": {
            "IndividualInformation": {
                "IndividualCode": "XXXXXX",
                "IndividualType": {
                    "Resident": 0,
                    "Alive": "Yes",
                }
            },FamilyInformation": {
                "FamilyCode": 0101010,
                "PresentInFamily": 1
            }
        },
        ..... 
}]

I am trying to handle this as there are 2 different reponses. I tried using JSON.deserializeUntyped. But for single reponse I have to use this (Map<String, Object>)JSON.deserializeUntyped(jsonBody);. Obviously doesn't work for array of response. For array I have to use (List<Object>) JSON.deserializeUntyped(jsonBody);. I can't simply cast it (List<Object>) for both array and single.

The only solution I found was:

String respBody = res.getBody();
if(!respBody.left(1).equalsIgnoreCase('[')) respBody = '[' + res.getBody() + ']';

dataFromSystemExternal = (List<ResponseSystemExternal>) JSON.deserialize(respBody, List<ResponseSystemExternal>.Class);

Basically, I am checking the very first char of the respBody to see if it is a '['. If not I am enclosing the respBody between '[' and ']' and deserializing the respBody into a List.

Is there any other solution?

3 Answers 3

0

I don't think there is a better way to go about this than you're already doing. Checking the first character is about as quick/easy/simple as it gets.

You could use the JSONParser class for this instead of JSON.deserialize()

List<ResponseSystemExternal> result = new List<ResponseSystemExternal>();
JSONToken token = JSONParser.getCurrentToken();

if(token == JSONToken.START_ARRAY) {
    // parse json objects in a loop, and add to the result list
} else if(token == JSONToken.START_OBJECT) {
    // parse a single json object and add to the result list
}

but that's going to be a lot longer and a lot more complex than your current approach.

Checking create explicit parse code in json2apex would get you most of the way (should just need some small tweaks to the arrayOfJSON2Apex() method so it could accept a single object instead of an array).

In general, I think of using JSONParser as a last resort. In most cases, it's like trying to use a semi-truck to get to the store down the road and pick up a birthday card as opposed to just walking or using a bike.

0
String jsonStr = '[{"name":"Ajay"}, {"name":"Sohan"}]';

Object obj = (Object)JSON.deserializeUntyped(jsonStr);

System.debug(obj instanceOf List<Object>);// it'll return true in case of an array of objects and false in case of a single object.
2
  • Personally, I'd prefer typed deserialization, and The type system in Apex has always been "broken" to a degree with respect to collections. That said, this probably should work. It's important to note that you need to specifically check if it's a List<Object> and not an Object (because x instanceOf Object doesn't give any useful information, and it also won't compile).
    – Derek F
    Commented May 19 at 13:49
  • I suppose that for completeness, you'd want to put the result in a List<Object> if it's not already a List<Object> so that the subsequent processing is the same. List<Object> result; if(obj instanceOf List<Object>) { result = (List<Object>)obj; } else { result = new List<Object>{ obj }; }
    – Derek F
    Commented May 19 at 13:51
-1

Personally I use JSON to Apex to deal with dynamic responses. https://json2apex.herokuapp.com/

Paste in the response with multiple customers and then create. It will give you a test class and class to parse the response.

Once you have the parser in Salesforce, the class that is doing the callout can reference the code like this.

Apex Code:

//Parsing the response through the generated class

ParserClassName parsedResponse = ParserClassName .parse(responseBody);

//Looping through the people that are returned

for(ParserClassName.person currentPerson: parsedResponse.response.person){

}

1
  • This doesn't seem to address the question at hand. Sure, you'd get a deserialization class for the case of multiple Person objects, but it wouldn't be able to handle the case of getting a single Person object without checking for and adding the [ and ] like OP is already doing.
    – Derek F
    Commented May 19 at 11:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .