Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 755
JamesG Avatar asked Mar 24 '16 21:03

JamesG


4 Answers

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.

like image 95
Amresh Venugopal Avatar answered Sep 19 '22 09:09

Amresh Venugopal


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.

like image 30
Jeremy Thompson Avatar answered Sep 20 '22 09:09

Jeremy Thompson


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.

like image 45
Ashwin Avatar answered Sep 21 '22 09:09

Ashwin


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.

like image 34
Gru Avatar answered Sep 19 '22 09:09

Gru