[SalesForce] Getting JSON_PARSER_ERROR while parsing JSON

What am i doing wrong due to which i am getting JSON_PARSER_ERROR, I am using code below to parse json below :

@RestResource(urlMapping='/Imbellus/CandidateScore')
global with sharing class ImbellusScoreController {
    // workbench request URL : /services/apexrest/Imbellus/CandidateScore
    @HttpPost   
    global static String captureScores(String scoreJson) {
        System.debug('Score JSON: '+scoreJson);
        ScoresList scoreLst = (ScoresList)JSON.deserialize(scoreJson, ScoresList.class);
        System.debug('----scoreLst----' + scoreLst);
        return '';
    }
    public class ScoresList {
        public List<Score> scores;
    }
    public class score {
        public String Overall_Behavioral_Score_c;
        public String Overall_Drive_Achieving_Score_c;
        public String Overall_Functional_Screen_Score_c;
        public String Overall_Leadership_Score_c;
        public String Interview_Overall_Score_c;

    }
}

URL in workbench
/services/apexrest/Imbellus/CandidateScore

json in request body

{
"scores":
[
{
"Overall_Behavioral_Score_c" : "50",
"Overall_Drive_Achieving_Score_c" : "60",
"Overall_Functional_Screen_Score_c" : "70",
"Overall_Leadership_Score_c" : "80",
"Interview_Overall_Score_c" : "90"
},
{
"Overall_Behavioral_Score_c" : "15",
"Overall_Drive_Achieving_Score_c" : "16",
"Overall_Functional_Screen_Score_c" : "17",
"Overall_Leadership_Score_c" : "18",
"Interview_Overall_Score_c" : "19"
}
]
}

[ { "message" : "Unexpected parameter encountered during
deserialization: scores at [line:3, column:2]", "errorCode" :
"JSON_PARSER_ERROR" } ]

Best Answer

The signature of the REST method is confusing Salesforce.

global static String captureScores(String scoreJson) {

should be

global static String captureScores(ScoresList inboundScoresList) {

With REST methods, Salesforce manages the deserialization for you based on an incoming JSON object whose keys map to the names of your parameters. Here, Salesforce is trying to deserialize your ScoresList JSON into an object containing a String whose key is scoresJson, which isn't working because it's a ScoresList that you yourself are hoping to deserialize. That's why you get an error "Unexpected parameter encountered" - Salesforce isn't expecting the parameter "scores", it's expecting "scoresJson", and the error's thrown before control hits your method and you attempt your own deserialization.

Changing the signature of the method and letting Salesforce do the deserialization should work.

Here's how to demonstrate this.

First, note that if you copy and paste the classes and the JSON into Anonymous Apex, you'll get no errors. Your code's correct if you assume that the incoming parameter is a string containing the JSON you show in your question.

But in Workbench, you get the JSON parser error when you send that JSON body.

If instead you embed your JSON string into an outer object with the key `"scoreJson", like this,

{"scoreJson" : "{\"scores\":[{\"Overall_Behavioral_Score_c\" : \"50\",\"Overall_Drive_Achieving_Score_c\" : \"60\",\"Overall_Functional_Screen_Score_c\" : \"70\",\"Overall_Leadership_Score_c\" : \"80\",\"Interview_Overall_Score_c\" : \"90\"},{\"Overall_Behavioral_Score_c\" : \"15\",\"Overall_Drive_Achieving_Score_c\" : \"16\",\"Overall_Functional_Screen_Score_c\" : \"17\",\"Overall_Leadership_Score_c\" : \"18\",\"Interview_Overall_Score_c\" : \"19\"}]}"}

it succeeds through Workbench REST Explorer with no code changes.

This is because Salesforce is able to deserialize this JSON blob to find a String parameter called scoreJson, which it passes to captureScores(). You then deserialize that string yourself once control reaches your method.

Related Topic