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, 2018 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, 2018 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, 2018 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, 2018 at 0:06
  • I did change the name of the class but still its the same issue.
    – Quddus
    Apr 2, 2018 at 0:12

1 Answer 1


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, 2018 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, 2018 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/… Apr 3, 2018 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, 2018 at 18:30

You must log in to answer this question.

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