I'm trying to write simple POST serverless Go AWS lambda function.
package main
import (
"fmt"
)
import (
"encoding/json"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
// RequestBodyType is our self-made struct to process JSON request from Client
type RequestBodyType struct {
Event string `string:"event,string,omitempty"`
EventParams EventParamsType
}
// ResponseBodyType is our self-made struct to build response for Client
type ResponseBodyType struct {
Event string `string:"event,string,omitempty"`
EventParams EventParamsType
}
// Probably problematic struct?
type EventParamsType struct {
Name string `json:"name,string,omitempty"`
Age int64 `json:"age,omitempty"`
}
// Handler function Using AWS Lambda Proxy Request
func Handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// RequestBody will be used to take the json response from client and build it
requestBody := RequestBodyType{
Event: "",
EventParams: EventParamsType{
Name: "",
Age: 0,
},
}
// Unmarshal the json, return 404 if error
err := json.Unmarshal([]byte(request.Body), &requestBody)
if err != nil {
return events.APIGatewayProxyResponse{Body: err.Error(), StatusCode: 404}, nil
}
// We will build the BodyResponse and send it back in json form
responseBody := &ResponseBodyType{
Event: requestBody.Event,
EventParams: EventParamsType{
Name: requestBody.EventParams.Name,
Age: requestBody.EventParams.Age,
},
}
fmt.Println("RESPONSE BODY")
fmt.Println(responseBody)
// Marshal the response into json bytes, if error return 404
response, err := json.Marshal(&responseBody)
if err != nil {
return events.APIGatewayProxyResponse{Body: err.Error(), StatusCode: 404}, nil
}
//Returning response with AWS Lambda Proxy Response
return events.APIGatewayProxyResponse{Body: string(response), StatusCode: 200}, nil
}
func main() {
lambda.Start(Handler)
}
Everything works fine if I make curl request with single JSON object key, for example:
curl -X POST https://my.url/dev/event -d '{"event": "test"}'
And I get response
{"Event":"test","EventParams":{}
But if I make request with nested json object, for example:
curl -X POST https://my.url/dev/event -d '{"event": "test","eventParams": {"name": "peter","age": 13}}'
Then I get response
json: invalid use of ,string struct tag, trying to unmarshal "peter" into string
I believe I have probably design EventParamsType wrong way? Or am I building ResponseBodyType wrong way?
As the error says, your use of ,string
is invalid for your JSON input. Remove it:
Name string `json:"name,omitempty"`
,string
can be valid in a JSON tag, and it indicates that the number should be marshaled as a string literal. In the case of a value which is already a string, that means it expects a JSON-quoted string (which your input apparently is not).
This is explained in the docs:
The "string" option signals that a field is stored as JSON inside a JSON-encoded string. It applies only to fields of string, floating point, integer, or boolean types. This extra level of encoding is sometimes used when communicating with JavaScript programs:
Int64String int64 `json:",string"`
See in the playground for more details.
Also, as @Adrian has pointed out, string:
is a meaningless tag (for the purpose of JSON (un)marshaling, anyway). You probably want json:
instead of string:
(although some library may use a tag called string:
... 🤷