在Go中处理JSON Post请求
所以我有下面的,这似乎非常hacky,我一直在想,Go比这更好的devise库,但我找不到一个Go处理POST请求的JSON数据的例子。 他们都formsPOST。
这是一个示例请求: curl -X POST -d "{\"test\": \"that\"}" http://localhost:8082/test
这里是embedded日志的代码:
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)) }
有一个更好的方法,对吧? 我只是难以find最佳做法。
(Go也被称为Golang到search引擎,并在这里提到所以其他人可以find它。)
请使用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) } defer req.Body.Close() log.Println(t.Test) }
你需要阅读req.Body
。 ParseForm
方法正在读取req.Body
,然后以标准的HTTP编码格式进行parsing。 你想要的是读取正文,并以JSON格式parsing它。
这是你的代码更新。
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)) }
这个确切的问题让我疯狂。 我的JSON Marshaller和Unmarshaller没有填充我的Go结构。 然后我在https://eager.io/blog/go-and-jsonfind了解决scheme:;
“和Go的所有结构一样,重要的是要记住,只有首字母大写的字段对于像JSON Marshaller这样的外部程序才是可见的。”
之后,我的Marshaller和Unmarshaller完美地工作了!
我从文档中find了以下示例,真的很有帮助(来源于此 )。
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
,并用const jsonStream
replaceMessage
结构:
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) } }
更新 :我还补充说, 这篇文章提供了一些关于使用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”来parsingJSON,而不是“SomeKey”(您将在内部使用它)。