یک Go API جدید برای JSON
آدرس مقاله: https://go.dev/blog/jsonv2 آدرس نظرات: https://news.ycombinator.com/item?id=50369106 امتیاز: 275 # نظرات: 125
مایکل پرت، جو تسای، دانیل مارتی، یوهان برندهورست-ساتزکورن، راجر پپه، کریس هاینز و دیمین نیل 4 نوامبر 2026
نشانگذاری شی جاوا اسکریپت (JSON) یک فرمت تبادل داده ساده است، محبوبترین قالب دادهای است که در اینترنت استفاده میشود و به طور گسترده توسط برنامههای Go خوانده و نوشته میشود. Go از قبل از Go 1.0 پشتیبانی از JSON را در کتابخانه استاندارد گنجانده است. ما ابتدا در مورد پشتیبانی از JSON در Go بیش از 15 سال پیش نوشتیم!
با گذشت زمان، بسته ها با نیازهای کاربران خود تکامل می یابند و کدگذاری/json نیز از این قاعده مستثنی نیست. سال گذشته، ما در مورد یک API آزمایشی جدید برای JSON نوشتیم که برای ایجاد بهبودها و اصلاحات مورد انتظار طولانی طراحی شده است.
پس از بازخورد و اصلاح بیشتر، بسته های جدید encoding/json/v2 و encoding/json/jsontext پایدار هستند و به طور کلی در Go 1.27 در دسترس هستند! این پست نسخه به روز شده مقاله معرفی آزمایش، تشریح مشکلات مربوط به encoding/json و معرفی بسته های جدید است.
به طور کلی، رمزگذاری/json به خوبی حفظ شده است. ثابت شده است که ایده مارشال کردن و حذف انواع Go دلخواه با مقداری نمایش پیشفرض در JSON، همراه با قابلیت سفارشیسازی نمایش، بسیار انعطافپذیر است. با این حال، در سال های پس از معرفی آن، کاربران مختلف کاستی های متعددی را شناسایی کرده اند.
اشکالات رفتاری مختلفی در encoding/json وجود دارد:
مدیریت نادقیق نحو JSON: در طول سال ها، JSON شاهد افزایش استانداردسازی برای برقراری ارتباط صحیح برنامه ها بوده است. به طور کلی، رمزگشاها در رد ورودی های مبهم سختگیرانه تر شده اند تا احتمال اینکه دو پیاده سازی تفسیرهای متفاوت (موفق) از یک مقدار خاص JSON داشته باشند را کاهش دهند.
encoding/json در حال حاضر UTF-8 نامعتبر را می پذیرد، در حالی که آخرین استاندارد اینترنت (RFC 8259) به UTF-8 معتبر نیاز دارد. رفتار پیشفرض باید خطا را در حضور UTF-8 نامعتبر گزارش کند، بهجای معرفی خرابی دادههای بیصدا، که ممکن است مشکلاتی را در پایین دست ایجاد کند.
encoding/json در حال حاضر اشیاء با نام اعضای تکراری را می پذیرد. RFC 8259 نحوه مدیریت نامهای تکراری را مشخص نمیکند، بنابراین یک پیادهسازی در انتخاب مقدار دلخواه، ادغام مقادیر، نادیده گرفتن مقادیر یا گزارش خطا آزاد است. وجود یک نام تکراری منجر به یک مقدار JSON بدون معنای مورد توافق جهانی می شود. این می تواند توسط مهاجمان در برنامه های امنیتی مورد سوء استفاده قرار گیرد و قبلا مورد سوء استفاده قرار گرفته است (مانند CVE-2017-12635). رفتار پیشفرض باید از نظر ایمنی اشتباه کند و نامهای تکراری را رد کند.
عدم نشت برشها و نقشهها: JSON اغلب برای برقراری ارتباط با برنامههایی با استفاده از پیادهسازیهای JSON استفاده میشود که اجازه نمیدهند null به نوع دادهای که انتظار میرود یک آرایه یا شی JSON باشد، تبدیل شود. از آنجایی که کدگذاری/json یک برش صفر یا یک نقشه را به عنوان یک JSON null نشان میدهد، این ممکن است منجر به خطا در هنگام حذف کردن توسط سایر پیادهسازیها شود. یک نظرسنجی نشان داد که اکثر کاربران Go ترجیح میدهند که برشها و نقشههای صفر بهصورت پیشفرض بهعنوان یک آرایه یا شی خالی JSON درج شوند.
unmarshaling حساس به حروف بزرگ و کوچک: هنگام حذف کردن، نام یک عضو شی JSON با استفاده از یک تطابق غیر حساس به حروف بزرگ به نام فیلد ساختار Go تبدیل میشود. این یک پیشفرض شگفتانگیز، یک آسیبپذیری امنیتی بالقوه و یک محدودیت عملکرد است.
فراخوانی ناسازگار متدها: به دلیل جزئیات پیاده سازی، متدهای MarshalJSON اعلام شده روی گیرنده اشاره گر به طور متناقض توسط encoding/json فراخوانی می شوند. در حالی که به عنوان یک باگ در نظر گرفته می شود، نمی توان آن را برطرف کرد زیرا بسیاری از برنامه ها به رفتار فعلی بستگی دارند.
API کدگذاری/json میتواند پیچیده یا محدودکننده باشد:
جداسازی صحیح از io.Reader دشوار است. کاربران اغلب json.NewDecoder(r).Decode(v) را می نویسند، که در انتهای ورودی ناخواسته دنباله دار را رد نمی کند.
گزینه ها را می توان بر روی انواع رمزگذار و رمزگشا تنظیم کرد، اما نمی توان آنها را با توابع Marshal و Unmarshal استفاده کرد. به طور مشابه، انواعی که رابطهای Marshaler و Unmarshaler را پیادهسازی میکنند، نمیتوانند از گزینهها استفاده کنند و هیچ راهی برای پایین آوردن گزینهها در پشته تماس وجود ندارد. به عنوان مثال، گزینه Decoder.DisallowUnknownFields هنگام فراخوانی یک متد سفارشی UnmarshalJSON اثر خود را از دست می دهد.
توابع Compact، Indent و HTMLEscape به جای چیزی انعطافپذیرتر مانند []byte یا io.Writer در یک بایت مینویسند. Buffer. این قابلیت استفاده از آن توابع را محدود می کند.
با کنار گذاشتن جزئیات پیاده سازی داخلی، API عمومی آن را به محدودیت های عملکرد خاصی متعهد می کند:
MarshalJSON: روش رابط MarshalJSON پیاده سازی را مجبور می کند که []بایت برگشتی را تخصیص دهد. همچنین، معناشناسی مستلزم آن است که encoding/json تأیید کند که نتیجه JSON معتبر است و همچنین آن را مجددا برای مطابقت با تورفتگی مشخص شده قالب بندی کند.
UnmarshalJSON: روش رابط UnmarshalJSON مستلزم آن است که یک مقدار JSON کامل (بدون هیچ گونه داده انتهایی) ارائه شود. این کار Encoding/json را مجبور میکند تا مقدار JSON را تجزیه و تحلیل کند تا قبل از فراخوانی UnmarshalJSON مشخص شود که کجا به پایان میرسد. پس از آن، خود متد UnmarshalJSON باید مقدار JSON ارائه شده را دوباره تجزیه کند.
عدم پخش جریانی: حتی اگر نوع رمزگذار و رمزگشا بر روی io.Writer یا io.Reader کار می کنند، کل مقدار JSON را در حافظه بافر می کنند. روش Decoder.Token برای خواندن توکنهای جداگانه، تخصیص سنگینی دارد و هیچ API متناظری برای نوشتن توکنها وجود ندارد.
علاوه بر این، اگر پیاده سازی یک متد MarshalJSON یا UnmarshalJSON به صورت بازگشتی تابع Marshal یا Unmarshal را فراخوانی کند، عملکرد درجه دوم می شود.
معرفی یک نسخه اصلی جدید و ناسازگار از یک بسته یک ملاحظه سنگین است. در صورت امکان، باید سعی کنیم بسته موجود را تعمیر کنیم.
در حالی که اضافه کردن ویژگی های جدید نسبتا آسان است، تغییر ویژگی های موجود دشوار است. متأسفانه، این مشکلات پیامدهای ذاتی API موجود هستند و رفع آنها را در وعده سازگاری Go 1 عملا غیرممکن میکند.
ما در اصل میتوانیم نامهای جداگانهای مانند MarshalV2 یا UnmarshalV2 را اعلام کنیم، اما این مساوی است با ایجاد یک فضای نام موازی در یک بسته. این ما را به encoding/json/v2 میبرد (از این پس v2 نامیده میشود)، که در آن میتوانیم این تغییرات را در یک فضای نام جداگانه v2 بر خلاف encoding/json (از این پس v1 نامیده میشود) انجام دهیم.
قبل از بحث در مورد v2 API، ابتدا بسته encoding/json/jsontext را معرفی میکنیم که پایهای برای بهبود JSON در Go است.
سریال سازی JSON در Go را می توان به دو جزء اصلی تقسیم کرد:
ما از اصطلاحات "رمزگشایی" و "رمزگشایی" برای توصیف عملکرد نحوی و اصطلاحات "مارشال" و "unmarshal" برای توصیف عملکرد معنایی استفاده می کنیم. هدف ما ارائه تمایز واضح بین عملکردی است که صرفا مربوط به رمزگذاری در مقابل مارشال است.
این نمودار یک نمای کلی از این جداسازی را ارائه می دهد. بلوک های بنفش نشان دهنده انواع هستند، در حالی که بلوک های آبی نشان دهنده توابع یا روش ها هستند. جهت فلش ها تقریبا نشان دهنده جریان داده ها است. نیمه پایینی نمودار، که توسط بسته jsontext پیادهسازی شده است، حاوی عملکردی است که فقط به نحو مربوط میشود، در حالی که نیمه بالایی که توسط بسته json/v2 پیادهسازی شده است، حاوی عملکردی است که معنای معنایی را به دادههای نحوی که توسط نیمه پایینی مدیریت میشود اختصاص میدهد.
بسته jsontext عملکردی را برای تعامل با JSON در سطح نحوی ارائه می دهد و نام خود را از RFC 8259، بخش 2 گرفته شده است که در آن دستور زبان داده های JSON به معنای واقعی کلمه JSON-text نامیده می شود. از آنجایی که فقط در سطح نحوی با JSON تعامل دارد، به بازتاب Go وابسته نیست.
رمزگذار و رمزگشا برای رمزگذاری و رمزگشایی مقادیر و نشانه های JSON پشتیبانی می کنند. سازنده ها گزینه های متغیری را می پذیرند که بر رفتار خاص رمزگذاری و رمزگشایی تأثیر می گذارد. برخلاف انواع رمزگذار و رمزگشا که در v1 اعلام شدهاند، انواع جدید در jsontext از به هم زدن تمایز بین نحو و معنایی جلوگیری میکنند و به شیوهای واقعا جریانی عمل میکنند.
یک مقدار JSON یک واحد کامل از داده است و در Go به عنوان یک []بایت نامگذاری شده است. مشابه RawMessage در نسخه 1 است که اکنون یک نوع نام مستعار برای jsontext.Value است. یک مقدار JSON از نظر نحوی از یک یا چند نشانه JSON تشکیل شده است. یک نشانه JSON در Go به عنوان نوع Token مات با سازنده ها و متدهای دسترسی نشان داده می شود. این شبیه به Token در نسخه 1 است اما طراحی شده است که نشان دهنده توکن های JSON دلخواه بدون تخصیص باشد.
برای حل مشکلات اساسی عملکرد با روشهای رابط MarshalJSON و UnmarshalJSON، ما به یک روش کارآمد برای رمزگذاری و رمزگشایی JSON به عنوان دنبالهای از توکنها و مقادیر نیاز داریم. در نسخه 2، ما متدهای رابط MarshalJSONTo و UnmarshalJSONFrom را معرفی میکنیم که بر روی رمزگذار یا رمزگشا کار میکنند و به پیادهسازی روشها اجازه میدهند تا JSON را به روشی کاملا جریانی پردازش کنند.
بنابراین، بسته json نیازی به اعتبارسنجی یا قالببندی یک مقدار JSON بازگردانده شده توسط MarshalJSON نیست، و همچنین نیازی به تعیین مرزهای یک مقدار JSON ارائه شده به UnmarshalJSON نیست. این مسئولیت ها به رمزگذار و رمزگشا تعلق دارد.
بر اساس بسته jsontext، اکنون بسته encoding/json/v2 را معرفی می کنیم. این طراحی شده است تا مشکلات موجود در v1 را برطرف کند، در حالی که برای کاربران بسته v1 آشنا باقی بماند. هدف ما این است که اگر مستقیما به v2 منتقل شود، استفاده از v1 عمدتا یکسان عمل می کند.
در اینجا، ما در درجه اول API سطح بالای v2 را پوشش می دهیم. برای مثالهایی در مورد نحوه استفاده از آن، ما خوانندگان را تشویق میکنیم که نمونههای بسته v2، آموزش «کار با JSON» را مطالعه کنند، یا وبلاگ Anton Zhiyanov را که این موضوع را پوشش میدهد، مطالعه کنند.
توابع Marshal و Unmarshal دارای امضایی مشابه v1 هستند، اما گزینه هایی را برای پیکربندی رفتار آنها می پذیرند. توابع MarshalWrite و UnmarshalRead مستقیما روی یک io.Writer یا io.Reader عمل میکنند، و از نیاز به ساخت موقت رمزگذار یا رمزگشا صرفا برای نوشتن یا خواندن از این نوعها اجتناب میکنند. توابع MarshalEncode و UnmarshalDecode بر روی یک jsontext.Encoder و jsontext.Decoder عمل می کنند و در واقع اجرای زیربنایی توابع ذکر شده قبلی است.
برخلاف v1، گزینهها یک آرگومان درجه یک برای هر یک از توابع مارشال و unmarshal هستند که انعطافپذیری و پیکربندی v2 را تا حد زیادی گسترش میدهند. چندین گزینه در نسخه 2 موجود است که در این مقاله پوشش داده نشده است.
مشابه v1، v2 به تیپها اجازه میدهد تا با برآورده کردن رابطهای خاص، نمایش JSON خود را تعریف کنند.
رابط های Marshaler و Unmarshaler با رابط های v1 یکسان هستند. رابط های جدید MarshalerTo و UnmarshalerFrom به یک نوع اجازه می دهد تا با استفاده از jsontext.Encoder یا jsontext.Decoder خود را به صورت JSON نشان دهد. این اجازه می دهد تا گزینه ها به پایین پشته تماس منتقل شوند، زیرا گزینه ها را می توان از طریق روش دسترسی به گزینه ها در رمزگذار یا رمزگشا بازیابی کرد.
مثال OrderedObject را برای نحوه پیاده سازی یک نوع سفارشی که ترتیب اعضای شی JSON را حفظ می کند، ببینید.
در نسخه 2، تماس گیرنده Marshal و Unmarshal همچنین می تواند یک نمایش JSON سفارشی را برای هر نوع دلخواه مشخص کند، که در آن توابع مشخص شده توسط تماس گیرنده بر روش های تعریف شده از نوع یا نمایش پیش فرض برای یک نوع خاص اولویت دارند.
MarshalFunc و MarshalToFunc یک marshaler سفارشی می سازند که می تواند با استفاده از WithMarshalers به فراخوانی Marshal منتقل شود تا مارشال کردن انواع خاص را لغو کند. به طور مشابه، UnmarshalFunc و UnmarshalFromFunc از سفارشی سازی مشابه برای Unmarshal پشتیبانی می کنند.
مثال ProtoJSON نشان میدهد که چگونه این ویژگی اجازه میدهد سریالسازی همه انواع proto.Message توسط بسته protojson انجام شود.
در حالی که هدف v2 این است که عمدتا مانند v1 رفتار کند، رفتار آن به جهاتی برای رفع مشکلات در v1 تغییر کرده است، به ویژه:
v2 یک خطا را در حضور UTF-8 نامعتبر گزارش می کند.
اگر یک شی JSON حاوی نام تکراری باشد، v2 خطا را گزارش می کند.
v2 یک slice یا نقشه Go را به ترتیب به عنوان یک آرایه JSON خالی یا یک شی JSON نشان می دهد.
v2 یک شی JSON را با استفاده از تطبیق حساس به حروف کوچک و بزرگ از نام عضو JSON تا نام فیلد Go به ساختار Go باز می کند.
v2 گزینه تگ omitempty را برای حذف یک فیلد در صورتی که به عنوان یک مقدار JSON "خالی" رمزگذاری شده بود (که null، "" ، [] و {} هستند) باز تعریف می کند.
v2 هنگام تلاش برای سریالسازی یک زمان، خطایی را گزارش میکند. مدت زمان، که در حال حاضر نمایش پیشفرض ندارد، اما گزینههایی برای تصمیمگیری به تماسگیرنده ارائه میدهد.
برای اکثر تغییرات رفتار، یک گزینه تگ ساختار یا گزینه مشخص شده توسط تماس گیرنده وجود دارد که می تواند رفتار را به گونه ای پیکربندی کند که تحت معنایی v1 یا v2 یا حتی سایر رفتارهای تعیین شده توسط تماس گیرنده عمل کند. برای اطلاعات بیشتر به " مهاجرت به نسخه 2 " مراجعه کنید.
عملکرد Marshal v2 تقریبا برابر با v1 است. گاهی اوقات کمی سریعتر است، اما گاهی اوقات کمی کندتر است. عملکرد Unmarshal نسخه 2 به طور قابل توجهی سریعتر از نسخه 1 است و معیارها تا 10 برابر بهبودهایی را نشان می دهند.
برای به دست آوردن دستاوردهای عملکردی بیشتر، پیادهسازیهای موجود Marshaler و Unmarshaler باید به پیادهسازی MarshalerTo و UnmarshalerFrom نیز مهاجرت کنند تا بتوانند از پردازش JSON به شیوهای صرفا جریانی بهره ببرند. به عنوان مثال، تجزیه بازگشتی مشخصات OpenAPI در روشهای UnmarshalJSON به طور قابلتوجهی به عملکرد سرویس خاصی از Kubernetes آسیب میزند (به kubernetes/kube-openapi#315 مراجعه کنید)، در حالی که تغییر به UnmarshalJSONFrom عملکرد بهبود یافته را بر اساس مرتبههای بزرگی تغییر میدهد.
برای جزئیات بیشتر معیار، به مخزن go-json-experiment/jsonbench مراجعه کنید.
علاوه بر پیشرفتهای ساختاری، ما همچنان به سرمایهگذاری در بهینهسازی عملکرد در پیادهسازی برای مواردی که اجرای v2 کندتر از v1 است، ادامه میدهیم. می توانید انتظار پیشرفت های بیشتری را در Go 1.28 داشته باشید.
وعده سازگاری Go 1 یک تضمین اصلی از پروژه Go است که به توسعه دهندگان اجازه می دهد برنامه هایی بسازند که در آزمون زمان مقاومت کنند و به کار بر روی نسخه های آینده Go ادامه دهند.
بستههای اصلی encoding/json و encoding/json/v2 جدید البته هر دو مشمول وعده سازگاری Go 1 هستند. برنامه هایی که از v1 استفاده می کنند به طور نامحدود پشتیبانی می شوند و هرگز نیازی به مهاجرت به نسخه 2 ندارند.
گفته شد، هنگام طراحی بستههای v2، ما میخواستیم بهتر از پشتیبانی از v1 انجام دهیم. ما میخواستیم اطمینان حاصل کنیم که v1 و v2 با یکدیگر سازگار هستند تا بستههایی که از نسخههای مختلف استفاده میکنند بتوانند با هم کار کنند. انجام این کار به جای اینکه کاربران را مجبور به استفاده از یک نسخه یا نسخه دیگر به دلیل انتخاب وابستگی هایشان کند، امکان مهاجرت آرام اکوسیستم را فراهم می کند.
به عنوان مثال، فرض کنید بسته شما از v2 استفاده می کند تا ساختاری حاوی فیلدی با یک نوع تعریف شده در بسته دیگر را به نمایش بگذارد. آن بسته ممکن است از روش اصلی v1 MarshalJSON برای تعریف رفتار مارشال کردن خود استفاده کند. مشکلی نیست، v2 از روشهای MarshalJSON پشتیبانی میکند، بنابراین مارشالسازی همانطور که انتظار میرود به کار خود ادامه میدهد.
برعکس، فرض کنید بسته شما از v1 برای مارشال کردن همان ساختار استفاده می کند. بسته دیگر ممکن است از روش v2 MarshalJSONTo برای عملکرد بهتر استفاده کند. در اینجا نیز مشکلی وجود ندارد، زیرا پیاده سازی v1 از متد MarshalJSONTo v2 در زیر هود پشتیبانی می کند.
ما با طراحی بستههای جدید به این هدف دست یافتهایم که در زیر هود، v1 بر حسب v2 پیادهسازی شود. همانطور که در بالا ذکر شد، v2 از گزینه های مختلفی پشتیبانی می کند. هر تفاوت رفتاری توسط یکی از این گزینه ها کنترل می شود. بنابراین، v1 را می توان از نظر v2 با عبور از مجموعه کامل گزینه های سازگاری v1 پیاده سازی کرد.
با این رویکرد، افزودنیهای سازگار با عقب مانند روشهای جدید (مانند MarshalJSONTo) یا تگهای ساختاری جدید (مثلا embed) بهطور خودکار به نفع کاربران فعلی نسخه ۱ پشتیبانی میشوند.
پیادهسازی v1 از نظر گزینههای v2 دارای مزیت دیگری است که امکان مهاجرت تدریجی سایتهای تماس را فراهم میکند.
encoding/json مجموعه کاملی از تفاوتهای رفتاری بین v1 و v2 را مستند میکند و کدام گزینه آن رفتارها را کنترل میکند.
بسیاری از برنامهها میتوانند مستقیما به v2 بدون تغییر رفتار قابل مشاهده مهاجرت کنند، اما برنامههایی که به رفتار v1 وابسته هستند، میتوانند از گزینهها برای تغییر تنها رفتارهایی که به آنها وابسته هستند استفاده کنند.
به عنوان مثال، ما میتوانیم همه رفتارهای v2 را انتخاب کنیم، به جز اجازه دادن به نامهای تکراری:
از طرف دیگر، ما میتوانیم همه رفتارهای v1 را انتخاب کنیم، بهجز عدم مجاز کردن نامهای تکراری:
راهنمای مهاجرت encoding/json/v2 به جزئیات بیشتری میپردازد و سناریوهای مختلفی را برای نزدیک شدن به انتقال یک برنامه از نسخه 1 به نسخه 2 پوشش میدهد.
برای ارجاعات بیشتر در مورد کار با بسته های جدید JSON، نگاه کنید به:
برنامه ریزی برای نسخه اصلی جدید رمزگذاری/json سال ها طول کشید. در اواخر سال 2020، به دلیل ناتوانی در رفع مشکلات بسته فعلی، دانیل مارتی (یکی از نگهبانان رمزگذاری/json) ابتدا افکار خود را در مورد اینکه یک بسته فرضی v2 باید چگونه باشد، ارائه کرد. به طور جداگانه، پس از کار قبلی بر روی Go API برای بافرهای پروتکل، جو تسای از اینکه بسته protojson نیاز به استفاده از پیادهسازی سفارشی JSON داشت، ناامید شد، زیرا رمزگذاری/json نه قادر به رعایت استاندارد سختگیرانهتر JSON که مشخصات بافر پروتکل مورد نیاز بود، نه کارآمد بود.
y سریالسازی JSON به شیوهای استریم.
دانیل و جو با اعتقاد به آینده ای روشن تر برای JSON سودمند و دست یافتنی بود، دانیل و جو نیروهای خود را به هم پیوستند تا در نسخه 2 به طوفان فکری بپردازند و شروع به ساخت یک نمونه اولیه کردند (که کد اولیه یک نسخه صیقلی از منطق سریال سازی JSON از ماژول Go protobuf است). با گذشت زمان، چند نفر دیگر (راجر پپه، کریس هاینز، یوهان برندهورست-ساتزکورن، دیمین نیل، آستین کلمنتز و مایکل پرت) با ارائه بررسی طراحی، بررسی کد و تست رگرسیون به این تلاش پیوستند. بسیاری از بحثهای اولیه در جلسات ضبطشده و یادداشتهای جلسه ما در دسترس عموم است.
بحثهای بعدی در یادداشتهای جلسه گروه کاری encoding/json/v2 ما موجود است.
این کار از ابتدا عمومی بوده است، و ما به طور فزایندهای جامعه Go را درگیر میکنیم، ابتدا با یک سخنرانی و بحث GopherCon که در اواخر سال 2023 ارسال شد، پیشنهاد رسمی ارسال شده در اوایل سال 2025، و در نهایت کدگذاری/json/v2 را به عنوان آزمایش Go در Go 1.25 برای آزمایش در مقیاس وسیعتر توسط همه کاربران Go اتخاذ کردیم.
تلاش v2 حدود 6 سال طول کشید تا به این نقطه رسید، بازخورد بسیاری از مشارکت کنندگان و همچنین کسب تجربه تجربی ارزشمند از استفاده در تنظیمات تولید.
شایان ذکر است که تا حد زیادی توسط افرادی که توسط Google استخدام نشده اند توسعه و ترویج شده است، و نشان می دهد که پروژه Go یک تلاش مشترک با یک جامعه جهانی پر رونق است که به بهبود اکوسیستم Go اختصاص دارد.
متن اصلی (انگلیسی)
A new Go API for JSON
Article URL: https://go.dev/blog/jsonv2 Comments URL: https://news.ycombinator.com/item?id=50369106 Points: 275 # Comments: 125