apaas.dev
7 November 2022
这是一个非常常见的任务:编码 JSON 并将其发送到服务器,在服务器上解码 JSON,反之亦然。令人惊讶的是,关于如何做到这一点的现有资源并不是很清楚。因此,让我们来看看每个案例,对于以下简单的 User 对象:
type User struct{
Id string
Balance uint64
}
在 POST/PUT 请求的正文中发送 JSON
让我们从最棘手的开始:Go 的 http.Request 的主体是一个 io.Reader,如果你有一个结构,它就不太适合 - 你需要先编写结构,然后将其复制到阅读器。
func main() {
u := User{Id: "US123", Balance: 8}
b := new(bytes.Buffer)
json.NewEncoder(b).Encode(u)
res, _ := http.Post("https://httpbin.org/post", "application/json; charset=utf-8", b)
io.Copy(os.Stdout, res.Body)
}
在服务器上解码 JSON
假设您希望客户端将 JSON 数据发送到服务器。很简单,用 json.NewDecoder(r.Body).Decode(&u) 解码它。以下是错误处理的样子:
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
var u User
if r.Body == nil {
http.Error(w, "Please send a request body", 400)
return
}
err := json.NewDecoder(r.Body).Decode(&u)
if err != nil {
http.Error(w, err.Error(), 400)
return
}
fmt.Println(u.Id)
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
在服务器响应中编码 JSON
与上述相反 - 调用 json.NewEncoder(w).Encode(&u) 将 JSON 写入服务器。
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
u := User{Id: "US123", Balance: 8}
json.NewEncoder(w).Encode(u)
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
从服务器读取 JSON 响应。
这次您将在发出请求后读取客户端中的响应正文。
func main() {
u := User{Id: "US123", Balance: 8}
b := new(bytes.Buffer)
json.NewEncoder(b).Encode(u)
res, _ := http.Post("https://httpbin.org/post", "application/json; charset=utf-8", b)
var body struct {
// httpbin.org sends back key/value pairs, no map[string][]string
Headers map[string]string `json:"headers"`
Origin string `json:"origin"`
}
json.NewDecoder(res.Body).Decode(&body)
fmt.Println(body)
}
而已!我希望它对你有很大帮助。请注意,我们只需要对字节数组的响应进行一次编码/解码 - 在其他所有情况下,我们都将其直接传递给读取器/写入器,这是 Go 和接口的真正优点之一 - 在大多数情况下,它是真的很容易传递流,而不必处理中间步骤。
- 登录 发表评论