Could not parse request body into json: Unexpected character (\'-\' (code 45)) AWS Lambda + API + Postman - json

I have been trying for a few days to get a parameter sent from the API Gateway in AWS to a Lambda function and I am having no success.
I decided to start from the beginning so I followed their walkthrough (http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started.html#getting-started-new-lambda)
I have checked this walkthrough twice and I have followed the steps to the letter.
Problem
When I test the API from Postman or in Swift I am getting the error:
{"message": "Could not parse request body into json: Unexpected character (\'-\' (code 45)) in numeric value: expected digit (0-9) to follow minus sign, for valid numeric value\n at [Source: [B#c036d15; line: 1, column: 3]"}
In postman, When I view the result as JSON I just get
Bad String
Lambda Function
The function is the basic example from the Walkthrough:
console.log('Loading event');
exports.handler = function(event, context) {
var name = (event.name === undefined ? 'No-Name' : event.name);
console.log('"Hello":"' + name + '"');
context.done(null, {"Hello":name}); // SUCCESS with message
};
When Tested from the Lambda Console and with the Test data I get the result:
{
"Hello": "TestUser123"
}
When Tested from the API Gateway Test, The result is also:
{
"Hello": "TestUser123"
}
Can anyone see why both test consoles are allowing this work but when tested with POSTMAN or used within a Swift Script it does not work ?
Edit 1
In postman, I have set the content-type to application/json
The script returns the default:
{
"Hello": "user"
}
However, When I add in the parameters name and TestUser123 in POSTMAN, this is when it returns the error.
Update 1
Ok, so I changed the mapping template to one that I found on another answer:
{ "name": "$input.params('name')" }
Now the result is:
{
"Hello": ""
}
Any Ideas why it is not getting the name?

I just got stuck with this today.
your mapping template is:
{ "name": "$input.params('name')" }
AWS uses AWS Velocity templates, which; even though looks like JSON, is different.
if you use
{ "name": $input.params('name') } // notice no quotes
for the mapping template right at the integration request step, then it should work as expected.

Read the error message very carefully, it actually tells you the problem. For example, I got
Could not parse request body into json: Unexpected character (\'\"\' (code 34)): was expecting comma to separate Object entries
So the problem is that I'm missing a comma. I check my Lambda's Integration Request - Body Mapping Template:
{
"age" : $input.json('$.persondata.age'),
"income" : $input.json('$.persondata.income')
"height" : $input.json('$.persondata.height')
}
Can you spot the problem? I am missing a comma after the income line.
Here is another example.
Could not parse request body into json: Unexpected character (\'}\' (code 125)): expected a value
When I look at the Integration Request - Body Mapping Template:
#set($inputRoot = $input.path('$'))
{
"age" : $inputRoot.age,
"height" : $inputRoot.height,
"income" : $inputRootincome
}
Can you spot the problem? I am missing a dot in $inputRootincome.

Error Message :
Could not parse request body into json: Could not parse payload into json: Unrecognized token \' \': was expecting (\'true\', \'false\' or \'null\')
Cause of the error : When string values inside the json are not assigned using double quotations in the aws mapping template the error occurs.
Solution : (Please Note : This example is for application/json type request template)
Actually the solution for the problem is, if you are using a value of type string in json then its value should be assigned inside a ("" - double quotation marks) in the mapping template.
The below shown example has the following attributes :
customerId - string (Please note : this value comes from a query parameter)
customerName - string
customerAge - integer
isPermanentEmployee - boolean
customerAddress - string (Please note this is an optional parameter)
And the mapping template should be defined like the example shown below
Refer the example below :
#set($inputRoot = $input.path('$'))
{
"CustomerId": "$input.params('customerId')",
"CustomerName": "$inputRoot.customerName",
"CustomerAge": $inputRoot.customerAge,
"IsPermanentEmployee": $inputRoot.isPermanentEmployee
"CustomerAddress ": #if($inputRoot.customerAddress == "") "" #elseif($inputRoot.customerAddress != "") "$inputRoot.customerAddress" #end
}
If you note the above mapping template, I would have given string values inside double quotation marks("") which will solve the error
Also this example contains how to handle optional parameters in aws mapping templates using #if#else statements.

It is likely that you had copy-pasted multiple lines in your "Integration Request" in the API gateway.
When copying a line and pasting it below, you might have copied the hidden character '\n' at the end of that line. This is probably causing issues at the lambda function.
Example: Copying the line containing age and pasting it twice and modifying them to have height and income respectively.
#set($inputRoot = $input.path('$'))
{
"age" : $inputRoot.age,
"height": $inputRoot.height,
"income": $inputRoot.income
}
Instead of copy-pasting, just type the line out for height and income.

Related

How to parse dynamic json reponse and get specific value and pass it as an input to next request

I get .json file as a response from an API and from that file I should parse and fins specific parameter and pass it as an input to the next request, how do I do that using Katalon.
If I say
response = JSON.parse("response.json");
it says it is unable to identify JSON as valid. Can someone help me out with the solution?
Your JSON is invalid, maybe it is a copy-paste issue.
The valid JSON should be
{
"responseStatusCode": "OK",
"data": {
"screenName": "employeeTimeslip",
"screenType": "Redirect",
"searchResultCount": 0,
"rows": [],
"tabs": [],
"searchParams": {
"employeeID": "000092926",
"timeslipNumber": "201900019701"
}
}
}
So, you were missing a "," between "OK" and "data" and two closing curly braces at the end of the file.
You can check JSON files for validity yourself using online JSON validators, for example, this one.
i found a way to read specific parameter from the json response file like below:
val scn = scenario("ClaimSubmission")
.exec(http("request_2")
.post("URL")
.headers(headers_2)
.body(RawFileBody("json file path"))
.check(jsonPath("$..timeslipnumber").find.saveAs("timeslipnumber")))
Timeslip number would be retrieved using : .check(jsonPath("$..timeslipnumber").find.saveAs("timeslipnumber")))

Google Apps Script API Request with GraphQL parse error

I'm trying to make API request with using Apps Script. API is GraphQL based.
I'm using JSON.stringify function. But API returns an error.
Request:
payload={"query":"{mutation {change_column_value (board_id: 177955, item_id: 287466289, column_id:\"phone\", value: \"{phone : 15065332974, countryShortName: \"US\" }\") {name column_values{ id value}}}"}}
I'm getting error;
{"errors":[{"message":"Parse error on \" }\" (STRING) at [1, 148]","locations":[{"line":1,"column":148}]}]}
Apps Script Code:
var us = "US"
var column_values = '{ \
mutation {change_column_value (board_id: 177955, item_id: '+ 287466289 +', column_id:"phone", value: "{phone : 15065332974, countryShortName: \"' + us +'\" }") {name column_values{ id value}} \
}';
settings = {
"method": "POST",
"headers": {"Content-Type" : "application/json","Authorization" : "eyJhbGciOiJIXXXXXXXXXX"},
"payload" : JSON.stringify({query:column_values})
}
response= UrlFetchApp.fetch(url, settings);
Brackets in a GraphQL operation indicate a selection set -- one or more fields that are being requested. The operation itself (whether a query or a mutation) is not a field, so you don't wrap the whole operation in brackets.
Correct:
mutation {
doSomething
}
Incorrect:
{
mutation {
doSomething
}
}
The only time you will see brackets that look like they are on the "outside" is when using query shorthand.
Provided that value is a String, then your use of backslashes to escape the double quotes inside that string should be fine.
You might also consider using variables, which would clean up your code considerably and make it less error prone.
You do not need to escape special characters inside a JSON request.
The syntax implies using key-value pairs assigned to each other with a colon, whereby strings are located inside quotes (not escaped with a backslash!), while numbers and variable names are not.
The brackets should be used in function of your desired API request as documented.

Getting an error while sending a json payload in quartz scheduler

I'm trying to send a json payload in quartz scheduler. I have the header set to Content-type:application/json, but for some reason my json string is throwing an error: Uncaught error, unexpected token in json.
The original json that I'm sending to a graphql service looks like this:
{
GetAllAuthors{
id
name
}
}
But to make it work in quartz, I need to mimic a rest API call, which is why I tried using the following:
{ "query":{{""{\nGetAllAuthors {\nid\nname\n}\n\n}""}} }
The above is also giving me the "Uncaught error, unexpected token in json" error. Is there something that I'm missing or overlooking?
PS: I tried using an online json formatter and when I try to validate the above json, I get the following error:
Error: Parse error on line 2:
{ "query": { { "" {\ nGetA
--------------^
Expecting 'STRING', '}', got '{'
That's not valid Json. This is how it might look if it were:
{
"GetAllAuthors": [
"id",
"name"
]
}
but I suspect you're trying for something like this:
{
"GetAllAuthors": {
"id": 123,
"name": "James Brown"
}
}
Play here until you get it right: https://jsonlint.com/
Edit: I've not worked with GraphQL, but this page shows how a (non JSON) GraphQL query might be transferred over Http by POSTing JSON or GETting using querystrings: https://graphql.org/learn/serving-over-http/
I figured this out by testing through Mozilla's network tab - the correct format is:
{"query":"{\n GetAllAuthors{\n id\n name\n}\n}\n","variables":null, "operationName":null}

How Can I parse out JSON in a Node-RED Function

I am working with Node-RED in Bluemix for IoT.
How can I parse out the individual pieces of information (like the cmdmsg and the tempr) in a function node so I can use it in other nodes in the flow?
I'm getting an error when I try (see below)
I am receiving the JSON complete message object (from an IoT in Node) that I see in my "debug" node when I set it to look at the complete message object. see the object below.
It appears to me that the JSON is formatted correctly.
I tried putting the following in the function node, but I'm getting an error that says "TypeError: Cannot read property 'tempr' of undefined"
Here is what the function parameter is:
return {payload:msg.payload.d.tempr};
and here is the message object
{
"topic": "iot-2/type/Arduino-tempsensor/id/FFFFFFFFFFFF/evt/status/fmt/json",
"payload": "{\n\"d\": {\n\"myName\": \"Arduino CF\",\n\"cmdmsg\": \"Weekly\",\n\"tempr\": -3,\n}\n}",
"deviceId": "FFFFFFFFFFFF",
"deviceType": "Arduino-tempsensor",
"eventType": "status",
"format": "json",
"_msgid": "ffffffff.55555"
}
note: I obfuscated the device ID (mac address) and msgid
Any ideas on how to parse the data out and why I'm getting an error?
Sorry, but your JSON Payload is completely messed up, it should look like this: {"d": {"myName": "Arduino CF","cmdmsg": "Weekly","tempr": -3}}
You shouldn't see any \or \nin the payload, they look like escape characters from the client side. I also believe that the last comma after the tempr value shouldn't be there for valid JSON.
I am not an Arduino expert but I have experimented with a Raspberry Pi and the Mosquitto client, this is how I can successfully send an event to IoTF:
mosquitto_pub -h <org>.messaging.internetofthings.ibmcloud.com -p 1883 -u "use-token-auth" -P "<token>" -i d:<org>:raspi:raspi2 -t iot-2/evt/message/fmt/json -m {"d":{"text":"Hello World"}}
If the paylod is correct JSON your statement return {payload:msg.payload.d.tempr}; will work.
Have you seen this: http://www.ibm.com/developerworks/cloud/library/cl-bluemix-arduino-iot2/
The JSON string you are showing should be converted to a Javascript object before you try to access its fields. To do that is as simple as wiring the arduino output to a "JSON" node, which does the conversion for you (or throws an error if the string is not valid JSON).
Wire the output of the JSON node to a debug node, if you want to see the structure of the msg object. You can also wire it to a "change" node, if you simply want to replace the msg.payload with the temperature value, for instance. You don't need any custom javascript code in a function node to do simple changes like that.
Here is a sample flow that you can import... the arduino output string is simulated by pasting your payload into a "template" node:
[{"id":"1a79abfe.b8abb4","type":"inject","z":"58c8eb7a.5496c4","name":"send output","topic":"iot-2/type/Arduino-tempsensor/id/FFFFFFFFFFFF/evt/status/fmt/json","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":2740,"wires":[["9fc678fb.ae18e8"]]},{"id":"69e91778.e0c6e8","type":"json","z":"58c8eb7a.5496c4","name":"","property":"payload","action":"","pretty":false,"x":390,"y":2800,"wires":[["d066800f.60a9b","cf991eb1.f2a1a"]]},{"id":"9d8d7da2.2a7da","type":"debug","z":"58c8eb7a.5496c4","name":"msg string","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":610,"y":2740,"wires":[]},{"id":"9fc678fb.ae18e8","type":"template","z":"58c8eb7a.5496c4","name":"arduino string","field":"payload","fieldType":"msg","format":"json","syntax":"plain","template":"{\n \"d\": {\n \"myName\": \"Arduino CF\",\n \"cmdmsg\": \"Weekly\",\n \"tempr\": -3\n }\n}","output":"str","x":360,"y":2740,"wires":[["69e91778.e0c6e8","9d8d7da2.2a7da"]]},{"id":"d066800f.60a9b","type":"change","z":"58c8eb7a.5496c4","name":"extract tempr","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.d.tempr","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":2860,"wires":[["af730d72.2995a"]]},{"id":"af730d72.2995a","type":"debug","z":"58c8eb7a.5496c4","name":"tempr","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":630,"y":2860,"wires":[]},{"id":"cf991eb1.f2a1a","type":"debug","z":"58c8eb7a.5496c4","name":"msg object","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":610,"y":2800,"wires":[]}]
As was noted, your original JSON string was not valid, because of the trailing comma -- but it is ok to have double-quotes and newlines as long as they are escaped with a "\". When the string is parsed, they are stripped out anyway.

Rally JSON I/O error creating a test case result

I am trying to create a test case result using a REST client, but get this error:
"Errors": ["Cannot parse input stream due to I/O error as JSON document: Parse error: expected '{' but saw '\uFFFF' [ chars read = >>>\uFFFF<<< ]"]
I get the same error when the name of the object, testcaseresult is not specified in the request body. Here are the steps to create a test case result using a browser REST client:
a) Generate the authorize key using "GET" method and the following URL:
https://rally1.rallydev.com/slm/webservice/v2.0/security/authorize
This is the response that I get back, with the security token: "123abc..."
{"OperationResult": {"_rallyAPIMajor": "2", "_rallyAPIMinor": "0", "Errors": [], "Warnings": [], "SecurityToken": "abc123..."}}
b) Use "POST" method, and the following URL:
https://rally1.rallydev.com/slm/webservice/v2.0/testcaseresult/create?key=abc123...
notice the security token in the end.
c) here is an example of a request body:
{
"testcaseresult":
{
"Build":"1",
"Tester":"/user/777",
"Date":"2010-09-04T19:56:05.000Z",
"TestCase":"/testcase/1111",
"Verdict":"Pass"
}
}
Only the required fields and the fields you want to set need to be referenced. Notice the outer key/value pair
{
"testcaseresult":{}
}
The fields that point to a full object, like "Tester" (points to User object) and "TestCase" (points to a TestCase object that owns the result) have to be referenced by their ObjectIDs:
"Tester":"/user/777",
"TestCase":"/testcase/1111",