5

I am trying to parse the JSON Response from a Composite REST API call into a wrapper class. However, from the docs, "body" attribute in the response from a Composite Subrequest will be an

Object

in case of a successful request, and will be an

Array

for a failed request.

Successful request:

{
  "body" : {       
    "id" : "001R00000033I6AIAU",
    "success" : true,
    "errors" : [ ]
  },
  "httpHeaders" : { 
    "Location" : "/services/data/v38.0/sobjects/Account/001R00000033I6AIAU"  
  },
  "httpStatusCode" : 201,
  "referenceId" : "refAccount"
}

Failed Request:

{
  "body" : [ {
    "message" : "Email: invalid email address: Not a real email address",
    "errorCode" : "INVALID_EMAIL_ADDRESS",
    "fields" : [ "Email" ]
  } ],
  "httpHeaders" : { },
  "httpStatusCode" : 400,
  "referenceId" : "badContact"
}

How can I parse the response into a Wrapper class if the body attribute in the wrapper is an object or an array?

I am using JSON.deserialize:

jsonResponseList.add((JSONCompositeRespObj)JSON.deserialize(res.getBody(), JSONCompositeRespObj.class));
  • 1
    there are plenty of posts addressing this issue, what error do you get when attempting to do the above? it should usually give you a clue what you need to deserialize your response into. be it a MAP, a List, etc, etc... – glls Dec 13 '17 at 14:50
  • 1
    Really weird that the success element isn't a top level element.. Does using JSON.deserializeUntyped(res) allow you to get the body element & type check from there? – battery.cord Dec 13 '17 at 14:53
  • No, really, these are responses for sub-requests rather than requests, so success isn't top level. And this is how SF sends the response so no way of altering the API response either. I think they should change it or at least make the names different. – SFDC Dev 27 Dec 15 '17 at 15:08
4

Since the success node isn't a top level element, you can't just use JSON.deserializeUntyped and get the element to determine the success, you need to rely on the type of the body.

Thankfully, JSON.deserializeUntyped provides the body element, and checking the type works very well here. An example is below.

String jsonFailure = '{ "body" : [ { "message" : "Email: invalid email address: Not a real email address", "errorCode" : "INVALID_EMAIL_ADDRESS", "fields" : [ "Email" ] } ], "httpHeaders" : { }, "httpStatusCode" : 400, "referenceId" : "badContact" }';
String jsonSuccess = '{ "body" : {"id" : "001R00000033I6AIAU", "success" : true, "errors" : [ ] }, "httpHeaders" : { "Location" : "/services/data/v38.0/sobjects/Account/001R00000033I6AIAU"}, "httpStatusCode" : 201, "referenceId" : "refAccount" }';

Map<String, Object> untypedSuccess = (Map<String, Object>)JSON.deserializeUntyped(jsonSuccess); 
Map<String, Object> untypedFailure = (Map<String, Object>)JSON.deserializeUntyped(jsonFailure); 

System.assertEquals(true, untypedFailure.get('body') instanceof List<Object>);
System.assertEquals(false, untypedSuccess.get('body') instanceof List<Object>);

There's probably a more complex or elegant way to solve this problem, but frankly, I'd rather modify the API response than write code to work with this response, but that isn't always possible.

  • Perfect, thanks a lot for the answer, seems my only way to go! And apologies for the late reply, was stuck up with something else.. – SFDC Dev 27 Dec 15 '17 at 15:05

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.