Chuyển đến nội dung chính
Mô-đun 8 · Bài học 5 trong tổng số 540/50 trong khóa học~14 min
Bài học theo mô-đun (5/5)

`mã hóa/json`

encoding/json là gói chuẩn để tuần tự hóa các cấu trúc Go thành JSON và ngược lại. Biết các quy ước và cạm bẫy của nó giúp bạn tiết kiệm hàng giờ gỡ lỗi trên API và tệp cấu hình.

Nguyên soái và Không nguyên soái

Hai chức năng chính:

Go
data, err := json.Marshal(v)      // Go → []byte JSON
err = json.Unmarshal(data, &v)    // JSON → Go (pass a pointer!)
Go
type User struct {
    Name  string
    Email string
}

u := User{Name: "Ada", Email: "ada@example.com"}
b, _ := json.Marshal(u)
fmt.Println(string(b))
// {"Name":"Ada","Email":"ada@example.com"}

var back User
_ = json.Unmarshal(b, &back)

Đối với đầu ra thụt lề (người có thể đọc được), hãy sử dụng json.MarshalIndent(v, "", " ").

Chỉ các trường đã xuất

json.Marshal chỉ tuần tự hóa các trường đã xuất (Chữ hoa). Các trường riêng tư bị bỏ qua âm thầm:

Go
type U struct {
    Name string // exported → serialized
    age  int    // private → ignored
}

Thẻ cấu trúc: kiểm soát tên và tùy chọn

Thẻ json:"..." kiểm soát tên, thiếu sót và loại trong đầu ra:

Go
type User struct {
    Name    string `json:"name"`                    // rename
    Email   string `json:"email,omitempty"`         // omit if zero value
    Private string `json:"-"`                       // never serialized
    ID      int    `json:"id,string"`               // number as string
}

Tùy chọn được sử dụng nhiều nhất:

  • ,omitempty — bỏ qua trường nếu đó là giá trị 0 (0, "", nil, lát/bản đồ trống).
  • ,- — chưa bao giờ được tuần tự hóa/giải tuần tự hóa.
  • ,string — gói số/bool dưới dạng chuỗi (hữu ích cho ID JS).

Bộ giải mã/Bộ mã hóa cho luồng

Khi làm việc với io.Reader/io.Writer (Nội dung HTTP, tệp lớn), hãy sử dụng Decoder và Encoder thay vì tải mọi thứ trong bộ nhớ:

Go
dec := json.NewDecoder(resp.Body)
var users []User
if err := dec.Decode(&users); err != nil {
    return err
}

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")
_ = enc.Encode(users)

Decoder cũng hỗ trợ dec.Token() để truyền phát phân tích cú pháp từng phần và dec.DisallowUnknownFields() để từ chối JSON bằng các khóa không mong muốn (hữu ích cho việc xác thực đầu vào).

Bản đồ chung và any

Nếu bạn không biết lược đồ, hãy giải tuần tự hóa thành map[string]any:

Go
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])

Các giá trị sẽ có loại động (string, float64 cho số, []any, map[string]any, bool, nil).

Các lỗi thường gặp

  • Quên &: json.Unmarshal(data, v) không điền bất cứ thứ gì; bạn cần &v.
  • Giải mã cấu trúc với các trường không: để tránh hoảng loạn, hãy kiểm tra err TRƯỚC KHI đọc các trường.
  • Các loại không tương thích: giải tuần tự hóa một số thành một chuỗi hoặc ngược lại trả về *json.UnmarshalTypeError.

Bài tập

tập thể dục#go.m8.l5.e1
Nỗ lực: 0Đang tải…

Tuần tự hóa cấu trúc u thành JSON bằng json.Marshal và in kết quả dưới dạng chuỗi.

Đang tải trình chỉnh sửa…

Giải pháp khả dụng sau 3 lần thử

tập thể dục#go.m8.l5.e2
Nỗ lực: 0Đang tải…

Giải tuần tự hóa `{"Name:"Ada"}` vào cấu trúc U bằng json.Unmarshal và in nó.

Đang tải trình chỉnh sửa…

Giải pháp khả dụng sau 3 lần thử

Quiz#go.m8.l5.e3
Sẵn sàng

Trường `chuỗi tên` (chữ thường) của cấu trúc có được json.Marshal đưa vào không?

Go
type U struct {
  name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))
Tùy chọn trả lời