Serialization/Encoding 在 json.NewEncoder 和 json.NewDecoder

Serialization/Encoding in json.NewEncoder and json.NewDecoder

我正在尝试通过使用 Go 中的 gorilla mux 库构建一个不同的基本 REST API 来学习后端开发(遵循这个 tutorial

这是我到目前为止构建的代码:

package main

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

"github.com/gorilla/mux"
)

// Post represents single post by user
type Post struct {
Title  string `json:"title"`
Body   string `json:"body"`
Author User   `json:"author"`
}

// User is struct that represnets a user
type User struct {
FullName string `json:"fullName"`
Username string `json:"username"`
Email    string `json:"email"`
}

var posts []Post = []Post{}

func main() {
   router := mux.NewRouter()
   router.HandleFunc("/posts", addItem).Methods("POST")
   http.ListenAndServe(":5000", router)
}

func addItem(w http.ResponseWriter, req *http.Request) {
   var newPost Post
   json.NewDecoder(req.Body).Decode(&newPost)

   posts = append(posts, newPost)

   w.Header().Set("Content-Type", "application/json")
   json.NewEncoder(w).Encode(posts)
}

但是,我真的很困惑 json.NewDecoderjson.NewEncoder 部分到底发生了什么。

据我了解,最终在 REST API 中通过互联网传输的数据将以 bytes/binary 格式的形式发生(我猜是用 UTF-8 编码?)。所以 json.NewEncoder 正在将 Go 数据结构转换为 JSON 字符串,而 json.NewDecoder 正在做相反的事情(如果我错了请纠正我)。

谁能解释一下在每个转换级别(json、二进制、内存中数据结构),数据传输到底是如何发生的?

  1. 调用json.NewEncoder产生的json.Encoder直接以UTF-8格式产生输出。无需转换。 (事实上​​ ,Go 没有与 UTF-8 编码字节序列不同的文本数据表示 - 即使 string 只是一个不可变的字节数组。)

  2. Go 使用术语 encode 进行序列化,使用 decode 进行反序列化,无论序列化形式是二进制还是文本.不要过多考虑术语——将 encodeseralise 视为同义词。

首先,我们必须明白,编码过程实际上并不意味着它将 types 和 returns 翻译成 type 的 JSON 表示。为您提供 JSON 表示的过程称为编组过程,可以通过调用 json.Marshal function.

来完成

另一方面,Encoding process means that we want to get the JSON encoding of any type and to write(encode) it on a stream that implements io.Writer interface. As we can see the func NewEncoder(w io.Writer) *Encoder receives an io.Writer interface as a parameter and returns a *json.Encoder object. When the method encoder.Encode() is being called, it does the Marshaling process and then writes the result to the io.Writer that we have passed when creating a new Encoder object. You could see the implementation of json.Encoder.Encode() here.

所以,如果你问谁对http流进行编码处理,答案就是http.ResponseWriter。 ResponseWriter 实现了 io.Writer 接口,当调用 Encode() 方法时,编码器会将对象编组为 JSON 编码表示,然后调用 func Write([]byte) (int, error) 这是一个合同io.Writer 接口的方法,它将执行对 http 流的写入过程。

总而言之,我可以说 Marshal 和 Unmarshal 意味着我们想要获得任何类型的 JSON 表示和 vice-versa。而 Encode 意味着我们要执行 Marshaling 过程,然后将结果写入(编码)到任何流对象。 Decode 意味着我们想从任何流中获取(解码)一个 json 对象,然后进行 Unmarshaling 过程。