在Go中返回JSON

How to I get JSON back from golang without it being encoded as a string? I am using this project to wrap go code in python so that I can execute it in an AWS lambda function.

My issue is that whether I return json.Marshal(obj) or string(json.Marshal(obj)) I either get the base64 encoded json or a string representation (e.g. "{\"bar\": \"foo\"}"). This is not an appropiate response if you are using the AWS API gateway as it expects pure json like you would get if you returned a json object in Node.js.

Here's my code:

package main

import "C"

import (
  "encoding/json"
  "github.com/eawsy/aws-lambda-go-core/service/lambda/runtime"
)

type Response struct {
  StatusCode  int       `json:"statusCode"`
  Headers     map[string]string  `json:"headers"`
  Body        string    `json:"body"`
}

func Handle(evt json.RawMessage, ctx *runtime.Context) (interface{}, error) {
  res := &Response{
    StatusCode: 1,
    Headers: map[string]string{"Content-Type": "application/json"},
    Body: "Hello World",
  }
  content, _ := json.Marshal(res)
  return string(content), nil
}

Here's the result I get from AWS:

enter image description here

https://play.golang.org/p/l2nrhG9lOA

It looks like the interface{} return type is the culprint. Forcing that to a string returns a more JSON-looking value. Having an interface{} return type makes me think something else is expecting a struct or marshal-able return value. Chase the interface{} or force a string and you should be good.

json.Marshal does return a pure JSON string. It looks like you're printing it with %q. See https://play.golang.org/p/skvAfk-frO.

Since AWS Lambda now officially supports Go, here is an revised example.

package main

import (
    "github.com/aws/aws-lambda-go/lambda"
)

// Response ...
type Response struct {
    StatusCode int               `json:"statusCode"`
    Headers    map[string]string `json:"headers"`
    Body       string            `json:"body"`
}

// Handle ...
func Handle() (Response, error) {
    return Response{
            StatusCode: 1,
            Headers:    map[string]string{"Content-Type": "application/json"},
            Body:       "Hello World",
        },
        nil
}

func main() {
    lambda.Start(Handle)
}


(Update below with another example)

You can also just use a map[string]interface{} data type directly without having to create a type.

package main

import (
    "github.com/aws/aws-lambda-go/lambda"
)

// Handle ...
func Handle() (map[string]interface{}, error) {
    return map[string]interface{}{
            "statusCode": 1,
            "headers":    map[string]string{"Content-Type": "application/json"},
            "body":       "Hello World",
        },
        nil
}

func main() {
    lambda.Start(Handle)
}