打印POSTJSON数据

Print POST JSON data

我在从 POST 打印 JSON 时遇到问题。 我使用 gorilla/mux 进行路由

r := mux.NewRouter()
r.HandleFunc("/test", Point).Methods("POST")
http.ListenAndServe(":80", r)`

Point 函数中我有

func Point(w http.ResponseWriter, r *http.Request) {
    var callback Decoder
    json.NewDecoder(r.Body).Decode(&callback)
}

但是只有当我知道结构并且我想弄清楚如何 log.Print 整个 JSON 作为一个字符串时,我才能使用这种方法。我试过了

func Point(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    log.Println(r.Form)
} 

但是它打印了一张空地图。请帮助解决这个问题。

如果您只需要原始 JSON 数据而不对其进行解析,http.Request.Body 实现 io.Reader,因此您可以从中直接 Read。例如 ioutil.ReadAll.

类似于(未测试):

func Point(w http.ResponseWriter, r *http.Request) {
    data, err := ioutil.ReadAll(r.Body)
    // check error
    // do whatever you want with the raw data (you can `json.Unmarshal` it too)
}

假设您正在构建一个接收一些 JSON 的标准 API 端点,并且您想用它做一些事情,您应该按照以下方式处理它。

编辑:

As mentioned in the comments when you use the ioutil.ReadAll() function as in this example it will read everything that is sent in the post request into the application memory. It's a good idea to check this in a production application (e.g limiting payload size).

1.) 在 GoLang
中创建一个结构来保存来自 API post 请求的数据 2.) 将您的请求正文转换为字节数组 []byte
3.) Unmarshal 你的 []byte 到你之前制作的结构的单个实例中。

下面我举个例子:

1。制作一个结构,您将把 JSON 放入其中。


我们以一个简单的博客为例post。

JSON 对象看起来像这样并且有一个 slug、一个 titledescription

{
  "slug": "test-slug",
  "title": "This is the title",
  "body": "This is the body of the page"
}

所以你的结构看起来像这样:

type Page struct {
    Slug  string `json:"slug"`
    Title string `json:"title"`
    Body  string `json:"body"`
}

2 - 3. 获取您的请求正文并将其转换为 byte[] 然后将该字符串 Unmarshal 放入您的结构实例中。


一个post请求的数据是请求'Body'.

在 Golang 中,几乎所有情况下的请求(除非您使用的是默认值之外的花哨的东西)都是 http.Request 对象。这是您通常在普通代码中拥有的 'r',它包含我们 POST 请求的 'Body'。

import (
    "encoding/json"
    "github.com/go-chi/chi" // you can remove
    "github.com/go-chi/render" // you can remove but be sure to remove where it is used as well below.
    "io/ioutil"
    "net/http"
)


func GiveMeAPage(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("A page"))
}

所以我们在这里要做的是将 io.ReadCloser,也就是 http.Request.Body 转换为 []byte,因为 Unmarshal 函数需要一个[]byte 类型。我已经在下面为您内联评论了。

func Create(w http.ResponseWriter, r *http.Request) {
    var p Page //Create an instance of our struct


    //Read all the data in r.Body from a byte[], convert it to a string, and assign store it in 's'.
    s, err := ioutil.ReadAll(r.Body) 
    if err != nil {
        panic(err) // This would normally be a normal Error http response but I've put this here so it's easy for you to test.
    }
    // use the built in Unmarshal function to put the string we got above into the empty page we created at the top.  Notice the &p.  The & is important, if you don't understand it go and do the 'Tour of Go' again.
    err = json.Unmarshal(s, &p)
    if err != nil {
        panic(err) // This would normally be a normal Error http response but I've put this here so it's easy for you to test.
    }

   // From here you have a proper Page object which is filled.  Do what you want with it.

    render.JSON(w, r, p) // This is me using a useful helper function from go-chi which 'Marshals' a struct to a json string and returns it to using the http.ResponseWriter.
}

As a side note. Please don't use Decoder to parse JSON unless you are using JSON streams. You are not here, and it's unlikely you will for a while. You can read about why that is here