所以我有以下,看起来非常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))
}
Run Code Online (Sandbox Code Playgroud)
必须有更好的方法,对吗?我很难找到最好的做法.
(Go也被称为搜索引擎的Golang,并在此处提到,以便其他人可以找到它.)
Joe*_*Joe 362
请使用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)
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*iel 79
你需要阅读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))
}
Run Code Online (Sandbox Code Playgroud)
小智 50
这个确切的问题让我发疯了.我的JSON Marshaller和Unmarshaller没有填充我的Go结构.然后我在https://eager.io/blog/go-and-json找到了解决方案:
"与Go中的所有结构一样,重要的是要记住只有具有大写第一个字母的字段才能被JSON Marshaller等外部程序看到."
在那之后,我的Marshaller和Unmarshaller完美地工作了!
col*_*tor 35
有两点原因json.Decoder
值得我们优先考虑json.Unmarshal
-2013年最受欢迎的答案中没有解决这些问题:
go 1.10
引入了一种新方法json.Decoder.DisallowUnknownFields() ,该方法解决了检测不需要的JSON输入的问题req.Body
已经是io.Reader
。json.Unmarshal
如果流是一个10MB的无效JSON块,则读取其全部内容然后执行操作会浪费资源。解析请求主体,用json.Decoder
的,因为它流中,如果遇到无效的JSON会引发早期解析错误。处理I / O流实时是首选去路。解决一些有关检测错误用户输入的用户评论:
要强制执行必填字段和其他卫生检查,请尝试:
d := json.NewDecoder(req.Body)
d.DisallowUnknownFields() // catch unwanted fields
// anonymous struct type: handy for one-time use
t := struct {
Test *string `json:"test"` // pointer so we can test for field absence
}{}
err := d.Decode(&t)
if err != nil {
// bad JSON or unrecognized json field
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
if t.Test == nil {
http.Error(rw, "missing field 'test' from JSON object", http.StatusBadRequest)
return
}
// optional extra check
if d.More() {
http.Error(rw, "extraneous data after JSON object", http.StatusBadRequest)
return
}
// got the input we expected: no more, no less
log.Println(*t.Test)
Run Code Online (Sandbox Code Playgroud)
典型输出:
$ curl -X POST -d "{}" http://localhost:8082/strict_test
expected json field 'test'
$ curl -X POST -d "{\"Test\":\"maybe?\",\"Unwanted\":\"1\"}" http://localhost:8082/strict_test
json: unknown field "Unwanted"
$ curl -X POST -d "{\"Test\":\"oops\"}g4rB4g3@#$%^&*" http://localhost:8082/strict_test
extraneous data after JSON
$ curl -X POST -d "{\"Test\":\"Works\"}" http://localhost:8082/strict_test
log: 2019/03/07 16:03:13 Works
Run Code Online (Sandbox Code Playgroud)
Joh*_*der 19
我发现文档中的以下示例非常有用(源于此处).
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)
}
}
Run Code Online (Sandbox Code Playgroud)
这里的关键是OP正在寻求解码
type test_struct struct {
Test string
}
Run Code Online (Sandbox Code Playgroud)
...在这种情况下,我们将删除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)
}
}
Run Code Online (Sandbox Code Playgroud)
更新:我还要补充一点,这篇文章也提供了一些关于使用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"`
}
Run Code Online (Sandbox Code Playgroud)
...现在你的处理程序将使用"some-key"解析JSON而不是"SomeKey"(你将在内部使用).
我喜欢在本地定义自定义结构。所以:
// my handler func
func addImage(w http.ResponseWriter, r *http.Request) {
// define custom type
type Input struct {
Url string `json:"url"`
Name string `json:"name"`
Priority int8 `json:"priority"`
}
// define a var
var input Input
// decode input or return error
err := json.NewDecoder(r.Body).Decode(&input)
if err != nil {
w.WriteHeader(400)
fmt.Fprintf(w, "Decode error! please check your JSON formating.")
return
}
// print user inputs
fmt.Fprintf(w, "Inputed name: %s", input.Name)
}
Run Code Online (Sandbox Code Playgroud)