Go encoding/json/v2: واجهة JSON جديدة مستقرة في Go 1.27
encoding/json/v2 و jsontext بقوا مستقرين في Go 1.27: سلوك أدق افتراضيًا، Unmarshal أسرع لحد 10x، و v1 لسه مدعوم.
يوم 4 نوفمبر 2026 فريق Go نشر على المدونة الرسمية إن encoding/json/v2 و encoding/json/jsontext بقوا مستقرين ومتاحين بشكل عام في Go 1.27. ده مش تجريب تاني — التجربة بدأت رسميًا في Go 1.25، والنهاردة الحزم دي دخلت المكتبة القياسية كـ GA.
ليه احتاجوا v2 أصلًا؟
encoding/json (اللي هنسميه v1) موجود من قبل Go 1.0 واشتغل كويس سنين طويلة. بس مع الوقت ظهرت مشاكل صعب تتصلح جوه نفس الـ API من غير ما يكسروا Compatibility Promise:
- قبول UTF-8 غلط (مع إن RFC 8259 بيطلب UTF-8 صحيح)
- قبول أسماء مكررة جوه نفس الـ object (وده اتستغل قبل كده في ثغرات زي CVE-2017-12635)
- الـ nil slice و الـ nil map بيتكتبوا
null، وده بيسبب أخطاء مع أنظمة تانية متستناشnullلمصفوفة أو object - مطابقة أسماء الحقول case-insensitive وقت الـ unmarshal
- خيارات على
Encoder/Decoderمش وصلة لـMarshal/Unmarshal، ومفيش streaming حقيقي
المحاولة إنهم يصلحوا v1 مباشرة اتصطدمت بوعد التوافق. فالحل كان namespace جديد: encoding/json/v2.
طبقتين: jsontext و json/v2
الفريق فصل الشغل لتين:
encoding/json/jsontext: النحو فقط (syntax) —EncoderوDecoderبيشتغلوا streaming حقيقي على tokens و values من غير reflectionencoding/json/v2: المعاني (semantics) — العلاقة بين قيم JSON وقيم Go، فوق jsontext
الـ API الأساسي لـ v2 مألوف:
json.Marshal(in any, opts ...Options) ([]byte, error)
json.MarshalWrite(out io.Writer, in any, opts ...Options) error
json.Unmarshal(in []byte, out any, opts ...Options) error
json.UnmarshalRead(in io.Reader, out any, opts ...Options) error
والجديد المهم للـ performance: واجهات streaming MarshalerTo و UnmarshalerFrom اللي بتشتغل على jsontext.Encoder / Decoder بدل ما ترجع []byte كامل وتعيد parse.
إيه اللي اتغيّر في السلوك؟
أهم الفروقات الافتراضية في v2 (حسب المقال الرسمي):
- خطأ عند UTF-8 غير صالح
- خطأ لو الـ object فيه اسم مكرر
- الـ nil slice → مصفوفة فاضية، والـ nil map → object فاضي
- مطابقة أسماء الحقول case-sensitive
omitemptyاتأعيد تعريفه: يتجاهل الحقل لو هيطلع قيمة JSON فاضية (nullأو""أو[]أو{})time.Durationمفيش تمثيل افتراضي — بيطلع error إلا لو حددت options
ومعظم الفروقات دي ليها option أو struct tag ترجعك لسلوك v1 لو محتاج.
الأداء والهجرة
حسب بنشماركات الفريق: Marshal تقريبًا زي v1 (ساعات أسرع شوية وساعات أبطأ)، أما Unmarshal أسرع بشكل واضح — لحد 10x في بعض الحالات. وفي Go 1.28 متوقع تحسينات إضافية في الحالات اللي v2 لسه فيها أبطأ من v1.
حاجة مهمة جدًا للـ ecosystem: v1 لسه مدعوم للأبد، ومش لازم تهاجر. وكمان تحت الغطا v1 بقى مبني على v2 بخيارات توافق — يعني packages بتستخدم v1 و v2 تقدر تشتغل مع بعض، و MarshalJSON القديمة لسه شغالة مع v2، و MarshalJSONTo الجديدة بتشتغل كمان من خلال v1.
لو عايز تهاجر تدريجي، تقدر تختار كل سلوك v2 ماعدا نقطة واحدة، أو العكس — زي السماح بالأسماء المكررة مع باقي سلوك v2.
رأيي
الـ JSON في Go كان محتاج تحديث من سنين، والفريق خد وقته (~6 سنين من أواخر 2020). المهم مش إنهم «بدّلوا الاسم» — المهم إن السلوك الافتراضي بقى أقرب للمعايير والأأمن، والـ Unmarshal بقى أسرع بشكل محسوس، والهجرة مش إجبار. لو بتكتب خدمة بتتعامل مع JSON كتير، جرّب v2 على مسار unmarshal تقيل وقِس قبل ما تنقل الـ production كله.
المصادر
- Go Blog — A new Go API for JSON: https://go.dev/blog/jsonv2
- Package
encoding/json/v2(docs عبر go.dev) - Package
encoding/json/jsontext
- Go
- Golang
- JSON
- Backend
- OpenSource
- encoding