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:
data, err := json.Marshal(v) // Go → []byte JSON
err = json.Unmarshal(data, &v) // JSON → Go (pass a pointer!)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:
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:
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ớ:
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:
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
errTRƯỚ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
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.
Giải pháp khả dụng sau 3 lần thử
Giải tuần tự hóa `{"Name:"Ada"}` vào cấu trúc U bằng json.Unmarshal và in nó.
Giải pháp khả dụng sau 3 lần thử
Trường `chuỗi tên` (chữ thường) của cấu trúc có được json.Marshal đưa vào không?
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))