Narendra Verma
Narendra Verma

Reputation: 2422

AWS API Gateway - Configuring Integration Request Mapping Templates to accept String body rather JSON

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.

  1. Opened the Integration Request settings and then Body Mapping Templates.
  2. Selected the option: When there are no templates defined (recommended)
  3. Added a mapping template for: application/json
  4. 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

Answers (2)

Narendra Verma
Narendra Verma

Reputation: 2422

My problem is resolved with simple change. As, I mentioned in my above question, I followed below steps.

  1. Opened the Integration Request settings and then Body Mapping Templates.

  2. Selected the option: When there are no templates defined (recommended)

  3. Added a mapping template for: application/json

  4. 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

bembas
bembas

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

Related Questions