Wrapper Class:

global class ApexDataContainer {
        public List<Purposes>purposes {get;set;}
        public class Purposes{
            public string purpose {get;set;}
            public string legalGround {get;set;}
            public string status {get;set;}
            public List<Description> description {get;set;}
            public string version {get;set;}
            public List<DataIds> dataIds {get;set;}

        public class Description {
            public string language {get;set;}
            public string text {get;set;}

        public class DataIds {


Callout Class:

public class CallDevam2 {
        public class deserializeResponse
            public String id;
            public String access_token;
        public CallDevam2(){
            ApexDataContainer c1 = new ApexDataContainer();
            ApexDataContainer.Purposes p1 = new ApexDataContainer.Purposes();
            ApexDataContainer.Description d1 = new ApexDataContainer.Description();
            ApexDataContainer.DataIds dIds = new ApexDataContainer.DataIds();       
            List<ApexDataContainer.Purposes> addtolist = new List<ApexDataContainer.Purposes>();
            List<ApexDataContainer.Description> addtodesc = new List<ApexDataContainer.Description>();
            List<ApexDataContainer.DataIds> addtodIds = new List<ApexDataContainer.DataIds>();
            p1.legalGround = 'MyGround';
            p1.purpose = 'purpose';
            p1.status = 'status';
            p1.version = 'version';
            d1.language = 'language';
            d1.text = 'text';
            p1.description = addtodesc;
            p1.dataIds = addtodIds;
            c1.purposes = addtolist;
            String jsonstr = JSON.serialize(c1);

            http http1 = new Http();
            HttpRequest req1 = new HttpRequest();
            req1.setHeader('Authorization','Bearer ' + token1); //The token which i had already recieved used here
            HttpResponse response1 = http1.send(req1);


I have seen in the debug log before making a call out that we have the valid json but once it hits the service I get the response as

00:41:07:354 USER_DEBUG [51]|DEBUG|response1:[{"message":"Unexpected parameter encountered during deserialization: purposes at [line:1, column:14]","errorCode":"JSON_PARSER_ERROR"}]

With the same json string if I do within classes, it gets successfully parsed, do we need to do anything extra in REST call out while sending Json request as string.

The exposed service class:

global class RESTservice {
    global static String resultsDisplay(String c1){
        ApexDataContainer resp2 = (ApexDataContainer)JSON.deserialize(c1, ApexDataContainer.class);
        return 'Connection established';
        }catch(exception e){
        return 'Connection Error';

The ApexDataContainer class is excatly same in both the environments. The request gets failed in the method invoke .

Any ideas , pls ....

  • 1
    What is the failing JSON string? – David Reed Apr 1 '18 at 23:44
  • This is the JSON debug from the above code: USER_DEBUG [28]|DEBUG|@@@{"purposes":[{"version":"version","status":"status","purpose":"purpose","legalGround":"MyGround","description":[{"text":"text","language":"language"}],"dataIds":[]}]} – Quddus Apr 1 '18 at 23:49
  • Error message: 00:41:07:354 USER_DEBUG [51]|DEBUG|response1:[{"message":"Unexpected parameter encountered during deserialization: purposes at [line:1, column:14]","errorCode":"JSON_PARSER_ERROR"}] – Quddus Apr 1 '18 at 23:50
  • I suspect, although I don't have a detailed explanation based on the internals of the JSON parser, that this is a namespace collision between the instance variable ApexDataContainer.purposes and the inner class ApexDataContainer.Purposes. – David Reed Apr 2 '18 at 0:06
  • I did change the name of the class but still its the same issue. – Quddus Apr 2 '18 at 0:12

Salesforce handles parameters to a rest service in a slightly funny way.

I'm pretty sure that your parameter is coming through like this:

  "c1": {
    "purposes": [
        "version": "version",
        "status": "status",
        "purpose": "purpose",
        "legalGround": "MyGround",
        "description": [
            "text": "text",
            "language": "language"
        "dataIds": []

ie, c1 is treated as a JSON attribute. So to get the rest of the object, you'd need to deserializeUntyped, grab purposes, stringify and finally deserialize.

Otherwise, you can skip the method param and use this technique:

String r = RestContext.request.requestBody.toString();
AuraDataContainer adc = (AuraDataContainer)JSON.deserialize(r, AuraDataContainer.class);
  • Yes, after lot of research I had used the Restcontext part yesterday because there the request body comes properly. But I am curious to know one thing as you explaned above that the entire body comes under c1, while sending the request body , I am doing.setbody which is a string and in the HTTPPOST method declartion global static String resultsDisplay(String c1) , this is also string. so why the parsing happening on the method call itself. String to String it sould not parse anything ? – Quddus Apr 2 '18 at 10:57
  • Even If i tried with this method structure it failed, @HttpPost global static String resultsDisplay(String c1){ try{ system.debug('1111'+c1); return 'Connection established'; }catch(exception e){ system.debug('$$$$'+e.getMessage()); return 'Connection Error'; } – Quddus Apr 2 '18 at 11:06
  • Remove the param. If there is a param, the requestbody will be null. Source: developer.salesforce.com/docs/atlas.en-us.apexcode.meta/… – Caspar Harmer Apr 3 '18 at 2:46
  • Yeah I got that concept of restcontext, I saw just curious why it was failing for normal param where as I saw sending the body as string ...Anyway its ok as long as we have workarounds. Thanks for our help. – Quddus Apr 3 '18 at 18:30

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.