首页 文章

在Go中处理JSON Post请求

提问于
浏览
192

所以我有以下,看起来非常hacky,我一直在想自己Go有更好的设计库,但是我找不到Go处理JSON数据的POST请求的例子 . 它们都是POST形式 .

以下是一个示例请求: curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test

这是代码,嵌入了日志:

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

type test_struct struct {
    Test string
}

func test(rw http.ResponseWriter, req *http.Request) {
    req.ParseForm()
    log.Println(req.Form)
    //LOG: map[{"test": "that"}:[]]
    var t test_struct
    for key, _ := range req.Form {
        log.Println(key)
        //LOG: {"test": "that"}
        err := json.Unmarshal([]byte(key), &t)
        if err != nil {
            log.Println(err.Error())
        }
    }
    log.Println(t.Test)
    //LOG: that
}

func main() {
    http.HandleFunc("/test", test)
    log.Fatal(http.ListenAndServe(":8082", nil))
}

必须有更好的方法,对吗?我很难找到最好的做法 .

(Go也被称为搜索引擎的Golang,这里提到其他人可以找到它 . )

4 回答

  • 14

    请使用 json.Decoder 而不是 json.Unmarshal .

    func test(rw http.ResponseWriter, req *http.Request) {
        decoder := json.NewDecoder(req.Body)
        var t test_struct
        err := decoder.Decode(&t)
        if err != nil {
            panic(err)
        }
        log.Println(t.Test)
    }
    
  • 299

    你需要阅读 req.Body . ParseForm 方法从 req.Body 读取,然后以标准HTTP编码格式解析它 . 你想要的是读取正文并以JSON格式解析它 .

    这是你的代码更新 .

    package main
    
    import (
        "encoding/json"
        "log"
        "net/http"
        "io/ioutil"
    )
    
    type test_struct struct {
        Test string
    }
    
    func test(rw http.ResponseWriter, req *http.Request) {
        body, err := ioutil.ReadAll(req.Body)
        if err != nil {
            panic(err)
        }
        log.Println(string(body))
        var t test_struct
        err = json.Unmarshal(body, &t)
        if err != nil {
            panic(err)
        }
        log.Println(t.Test)
    }
    
    func main() {
        http.HandleFunc("/test", test)
        log.Fatal(http.ListenAndServe(":8082", nil))
    }
    
  • 62

    这个确切的问题让我发疯了 . 我的JSON Marshaller和Unmarshaller没有填充我的Go结构 . 然后我在https://eager.io/blog/go-and-json找到了解决方案:

    “与Go中的所有结构一样,重要的是要记住只有具有大写第一个字母的字段才能被外部程序看作,如JSON Marshaller . ”

    在那之后,我的Marshaller和Unmarshaller工作得很好!

  • 33

    我发现文档中的以下示例非常有用(源here) .

    package main
    
    import (
        "encoding/json"
        "fmt"
        "io"
        "log"
        "strings"
    )
    
    func main() {
        const jsonStream = `
            {"Name": "Ed", "Text": "Knock knock."}
            {"Name": "Sam", "Text": "Who's there?"}
            {"Name": "Ed", "Text": "Go fmt."}
            {"Name": "Sam", "Text": "Go fmt who?"}
            {"Name": "Ed", "Text": "Go fmt yourself!"}
        `
        type Message struct {
            Name, Text string
        }
        dec := json.NewDecoder(strings.NewReader(jsonStream))
        for {
            var m Message
            if err := dec.Decode(&m); err == io.EOF {
                break
            } else if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("%s: %s\n", m.Name, m.Text)
        }
    }
    

    这里的关键是OP正在寻求解码

    type test_struct struct {
        Test string
    }
    

    ...在这种情况下,我们将删除 const jsonStream ,并将 Message 结构替换为 test_struct

    func test(rw http.ResponseWriter, req *http.Request) {
        dec := json.NewDecoder(req.Body)
        for {
            var t test_struct
            if err := dec.Decode(&t); err == io.EOF {
                break
            } else if err != nil {
                log.Fatal(err)
            }
            log.Printf("%s\n", t.Test)
        }
    }
    

    Update :我还要补充一点,this post提供了一些关于使用JSON进行响应的优秀数据 . 作者解释 struct tags ,我不知道 .

    由于JSON通常看起来不像 {"Test": "test", "SomeKey": "SomeVal"} ,而是 {"test": "test", "somekey": "some value"} ,因此您可以像这样重构结构:

    type test_struct struct {
        Test string `json:"test"`
        SomeKey string `json:"some-key"`
    }
    

    ...现在你的处理程序将使用“some-key”解析JSON而不是“SomeKey”(你将在内部使用) .

相关问题