-4

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?

1
  • string:"event,string,omitempty" should be json:"event,string,omitempty". Also you don't need to specify string if the struct field type is already string. Commented Jun 3, 2021 at 15:14

1 Answer 1

1

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:... 🤷

Sign up to request clarification or add additional context in comments.

1 Comment

You are right! I get the response now from AWS. Thank you for all informations.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.