שיעורי מודול (5/5)
'קידוד/json'
encoding/json היא החבילה הקנונית להסדרת מבני Go ל-JSON ובחזרה. הכרת המוסכמות והמלכודות שלו חוסכת לך שעות של ניפוי באגים בממשקי API וקבצי תצורה.
מרשל ואנמרשל
שתי הפונקציות העיקריות:
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)עבור פלט מוזח (ניתן לקריאה לאדם) השתמש ב-json.MarshalIndent(v, "", " ").
שדות מיוצאים בלבד
json.Marshal מסדרת רק שדות מיוצאים (אותיות גדולות). מתעלמים משדות פרטיים בשקט:
type U struct {
Name string // exported → serialized
age int // private → ignored
}תגיות מבנה: שליטה בשם ובאפשרויות
התגיות json:"..." שולטות בשם, השמטה וסוגים בפלט:
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
}האפשרויות הנפוצות ביותר:
,omitempty- משמיט את השדה אם הוא ערך אפס (0, "", אפס, פרוסה/מפה ריקה).,-- אף פעם לא הוצא בסידרה/מבוזרת.,string- עוטף מספרים/בולים כמחרוזות (שימושי עבור מזהי JS).
מפענח/מקודד לזרמים
בעבודה עם io.Reader/io.Writer (גוף HTTP, קבצים ענקיים) השתמשו ב-Decoder וEncoder במקום לטעון הכל בזיכרון:
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 תומך גם ב-dec.Token() לניתוח חלק אחר חלק וdec.DisallowUnknownFields() כדי לדחות JSON עם מפתחות לא צפויים (שימושי לאימות קלט).
מפות כלליות וany
אם אינך מכיר את הסכימה, פנה לסידריאל ל-map[string]any:
var v map[string]any
_ = json.Unmarshal(data, &v)
fmt.Println(v["name"])לערכים יהיו סוגים דינמיים (string, float64 למספרים, []any, map[string]any, bool, nil).
שגיאות נפוצות
- שכחת
&:json.Unmarshal(data, v)לא מאכלסת כלום; אתה צריך&v. - פענוח מבנים עם שדות אפס: כדי למנוע פאניקה, סמן
errלפני קריאת שדות. - סוגים לא תואמים: ביטול סדרה של מספר למחרוזת או להיפך מחזירה
*json.UnmarshalTypeError.
תרגילים
עשה בסידרה את ה-struct u ל-JSON עם json.Marshal והדפיס את התוצאה כמחרוזת.
הפתרון זמין לאחר 3 ניסיונות
הסר את `{"Name":"Ada"}` לתוך ה-struct U עם json.Unmarshal והדפיס אותו.
הפתרון זמין לאחר 3 ניסיונות
האם השדה `מחרוזת שם` (אותיות קטנות) של מבנה כלול ב-json.Marshal?
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))