跳转到主要内容

这是一个非常常见的任务:编码 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 和接口的真正优点之一 - 在大多数情况下,它是真的很容易传递流,而不必处理中间步骤。

文章链接