I attempted to send an HTTP request and transmit a JSON to the Salesforce REST API in the following manner, but encountered the following error:
Error: [ { "message": "JSON request body must be an object at [line:1, column:2]", "errorCode": "JSON_PARSER_ERROR" } ]
I have confirmed that the message is sent in JSON format. How can I correct this error?
This is my Apex code:
@RestResource(urlMapping='/apex_rest_api_endpoint/*')
global with sharing class CreateTask {
@HttpPost
global static String receiveAndProcessData(String jsonBodyList) {
Map<String, Object> requestData = (Map<String, Object>) JSON.deserializeUntyped(jsonBodyList);
String lineUserId = (String) requestData.get('userId');
String lineChannelId = (String) requestData.get('channel');
And my python code:
def get_json_msg(event, context):
if validate_signature_taichung(event['headers']['x-line-signature'],event)==True:
data = {
'userId': get_line_userid(event, context),
'message': get_line_message(event, context),
'channel': "xxxxxxx"
}
elif validate_signature_taipe(event['headers']['x-line-signature'],event)==True:
data = {
'userId': get_line_userid(event, context),
'message': get_line_message(event, context),
'channel': "xxxxxxx"
}
json_body = {"jsonBodyList": data}
return json.dumps(json_body)
def send_msg_to_customapi(event, context):
json_msg = get_json_msg(event, context)
print(json_msg)
params = {
"grant_type": "password",
"client_id": "xxxxxxxx", # Consumer Key
"client_secret": "xxxxxxxx", # Consumer Secret
"username": "xxxx@xxxxx", # The email you use to login
"password": "xxxxxxxx" # Concat your password and your security token
}
r = requests.post("https://login.salesforce.com/services/oauth2/token", params=params)
access_token = r.json().get("access_token")
instance_url = r.json().get("instance_url")
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
# Salesforce Apex REST API URL
api_endpoint = f"{instance_url}/services/apexrest/apex_rest_api_endpoint"
# HTTP POST
response = requests.post(api_endpoint, headers=headers, json=json_msg)
get_json_msg
has twoif
-conditions and noelse
- how isdata
guaranteed to have have a value? What doesprint(json_msg)
print?jsonBodyList
(which is not a list/array at all) from the request:Map<String, Object> requestData = (Map<String, Object>) JSON.deserializeUntyped(RestContext.request.requestBody.toString());
. Alternatively, set up an inner class with the shape of your JSON and declare this as the type of your parameterglobal static String receiveAndProcessData(JsonBodyList jsonBodyList)...
. In neither case state the parameter of the @HttpPost method as a String.Map<String, Object> requestData = (Map<String, Object>) JSON.deserializeUntyped(RestContext.request.requestBody.toString());
, but this time I received this error code: error:[ { "errorCode": "APEX_ERROR", "message": "System.TypeException: Invalid conversion from runtime type String to Map<String,ANY>\n\nClass.CreateTask.receiveAndProcessData: line 8, column 1" } ]
requests.post
has ajson
parameter--if you use it, it expects an object, not a JSON-string, so the data becomes double-encoded because of thejson.dumps
call. Further, the parameter was fine, but there needs to be arequest
wrapper, as demonstrated in my answer.