דילוג לתוכן המרכזי
מודול 8 · שיעור 5 מתוך 540/50 בקורס~14 min
שיעורי מודול (5/5)

'קידוד/json'

encoding/json היא החבילה הקנונית להסדרת מבני Go ל-JSON ובחזרה. הכרת המוסכמות והמלכודות שלו חוסכת לך שעות של ניפוי באגים בממשקי API וקבצי תצורה.

מרשל ואנמרשל

שתי הפונקציות העיקריות:

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)

עבור פלט מוזח (ניתן לקריאה לאדם) השתמש ב-json.MarshalIndent(v, "", " ").

שדות מיוצאים בלבד

json.Marshal מסדרת רק שדות מיוצאים (אותיות גדולות). מתעלמים משדות פרטיים בשקט:

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

תגיות מבנה: שליטה בשם ובאפשרויות

התגיות json:"..." שולטות בשם, השמטה וסוגים בפלט:

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
}

האפשרויות הנפוצות ביותר:

  • ,omitempty - משמיט את השדה אם הוא ערך אפס (0, "", אפס, פרוסה/מפה ריקה).
  • ,- - אף פעם לא הוצא בסידרה/מבוזרת.
  • ,string - עוטף מספרים/בולים כמחרוזות (שימושי עבור מזהי JS).

מפענח/מקודד לזרמים

בעבודה עם io.Reader/io.Writer (גוף HTTP, קבצים ענקיים) השתמשו ב-Decoder וEncoder במקום לטעון הכל בזיכרון:

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 תומך גם ב-dec.Token() לניתוח חלק אחר חלק וdec.DisallowUnknownFields() כדי לדחות JSON עם מפתחות לא צפויים (שימושי לאימות קלט).

מפות כלליות וany

אם אינך מכיר את הסכימה, פנה לסידריאל ל-map[string]any:

Go
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.

תרגילים

פעילות גופנית#go.m8.l5.e1
ניסיונות: 0טוען...

עשה בסידרה את ה-struct u ל-JSON עם json.Marshal והדפיס את התוצאה כמחרוזת.

טוען עורך...

הפתרון זמין לאחר 3 ניסיונות

פעילות גופנית#go.m8.l5.e2
ניסיונות: 0טוען...

הסר את `{"Name":"Ada"}` לתוך ה-struct U עם json.Unmarshal והדפיס אותו.

טוען עורך...

הפתרון זמין לאחר 3 ניסיונות

Quiz#go.m8.l5.e3
מוכן

האם השדה `מחרוזת שם` (אותיות קטנות) של מבנה כלול ב-json.Marshal?

Go
type U struct {
  name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))
אפשרויות תשובה