دروس الوحدة (5/5)
"الترميز/json".
encoding/json هي الحزمة الأساسية لإجراء تسلسل بنيات Go إلى JSON والعودة. إن معرفة اصطلاحاته ومزالقه توفر عليك ساعات من تصحيح الأخطاء في واجهات برمجة التطبيقات وملفات التكوين.
المارشال وأونمارشال
الوظيفتين الرئيسيتين:
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.
تمارين
قم بإجراء تسلسل للهيكل u إلى JSON باستخدام json.Marshal وطباعة النتيجة كسلسلة.
الحل متاح بعد 3 من المحاولات
قم بإلغاء تسلسل `{"Name": "Ada"}` في البنية U باستخدام json.Unmarshal ثم قم بطباعته.
الحل متاح بعد 3 من المحاولات
هل تم تضمين الحقل "سلسلة الاسم" (أحرف صغيرة) للبنية بواسطة json.Marshal؟
type U struct {
name string
}
b, _ := json.Marshal(U{name: "Ada"})
fmt.Println(string(b))