JamesG
JamesG

Reputation: 1601

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?

Upvotes: 30

Views: 106039

Answers (5)

Christopher Settles
Christopher Settles

Reputation: 403

I ran into this issue today, it was because I had binary media type set to */* in my API settings.

enter image description here

Upvotes: 2

Gru
Gru

Reputation: 965

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.

Upvotes: 2

Ashwin
Ashwin

Reputation: 51

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.

Upvotes: 5

Jeremy Thompson
Jeremy Thompson

Reputation: 65564

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.

Upvotes: 5

Amresh Venugopal
Amresh Venugopal

Reputation: 9549

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.

Upvotes: 14

Related Questions