Reputation: 2422
I have a spring boot application with GET method like below. This method has input parameter as String that is mapped with path variable {userId}.
@GetMapping("/users/{userId}")
public String get(@PathVariable ("userId") String userId) {
return userId;
}
I created AWS lambda function and uploaded my spring boot JAR. I am able to test lambda fuction with test event after passing string example "userId1". Lambda function worked fine.
Using API gateway, created API, defined resource and GET method. URL looks like below:
/users/{userId} - GET - Integration Request
Also, followed below steps to define Mapping Templates.
Added the following template to map the userId to the Lambda input
{ "userId": "$input.params('userId')" }
When I test my API, it gives me below exception. I am not sure, how I should define Mapping Templates so that it accepts only String rather JSON. Because my Lambda function and corresponding implemented method accepts only String. Thanks in advance for help.
{
"errorMessage": "An error occurred during JSON parsing",
"errorType": "java.lang.RuntimeException",
"stackTrace": [],
"cause": {
"errorMessage": "com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@69b2283a; line: 1, column: 1]",
"errorType": "java.io.UncheckedIOException",
"stackTrace": [],
"cause": {
"errorMessage": "Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@69b2283a; line: 1, column: 1]",
"errorType": "com.fasterxml.jackson.databind.JsonMappingException",
"stackTrace": [
"com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)",
"com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:857)",
"com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:62)",
"com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:11)",
"com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1511)",
"com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1102)"
]
}
}
}
Upvotes: 0
Views: 2331
Reputation: 2422
My problem is resolved with simple change. As, I mentioned in my above question, I followed below steps.
Opened the Integration Request settings and then Body Mapping Templates.
Selected the option: When there are no templates defined (recommended)
Added a mapping template for: application/json
Added the following template to map the userId to the Lambda input
{ "userId": "$input.params('userId')" }
In last step #4, I replaced below JSON format with String format.
{ "userId": "$input.params('userId')" }
With below, it worked. My API could pass String parameter properly to my lambda function which has handler method with one single input of type String.
$input.params('userId')
Upvotes: 0
Reputation: 771
I think that your problem occurred because you are mapping a JSON like:
{
"key1": "value1",
"key2": "value2",
"key3": "value3",
"key4": {
"sub_key1": "value4"
}
}
This containt a key key4
with and JSON object as value. When your are trying to deserialize this element, it won't work directly because it sees a JSON_OBJECT
, not a String.
You need to create a class like the following one:
public class Name { // the name doesn't matter
@JsonProperty("sub_key1")
private String sub_key1;
// getter and setter
}
to solve your problem.
Upvotes: 0