العربية

أدوات المطور · JSON المنسق والمدقق

معرفات الأعداد الصحيحة الكبيرة في JSON: لماذا قد تقوم منسقات JavaScript بتقريبها

· لماذا يهم

json سير عمل المطور تصديق

معرفات أعداد صحيحة كبيرة في JSON: لماذا قد تقوم منسقات JavaScript بتقريبها موضحة برموز JSON المميزة وحدود التحقق الدقيقة
الرسم التوضيحي المتجه الأصلي ToolAcre

JSON يسمح بالأعداد الصحيحة من أي حجم، ولكن JavaScript يمثل الأرقام كـ 64-bit floats، لذا فإن أي شيء أعلى من 2^53 يمكن أن يتغير عند تحليله وإعادة تسلسله. يشرح هذا المنشور الحد وكيفية اكتشاف الضرر وكيفية حماية المعرفات.

المعرف الذي تغير بواحد

غالبًا ما يصل المعرف الذي تم تغييره بواحد إلى JSON صالحًا تمامًا. ضع `{"orderId":9007199254740993}` في JavaScript وستقوم `JSON.parse` بإرجاع رقم قيمته المعروضة هي `9007199254740992`. نجح التحليل لأن الرمز المميز يتبع القواعد النحوية للأرقام JSON؛ يحدث الضرر أثناء تحويل تلك الأرقام العشرية إلى تمثيل رقمي لـ JavaScript. يقوم المنسق الذي يقوم بتسلسل القيمة التي تم تحليلها بكتابة الرقم الدائري بأمانة، وليس الرمز المميز الدقيق الذي ظهر في المصدر.

يكون التباين فوريًا عندما يتم نقل نفس الأرقام. `JSON.parse("{"orderId":"9007199254740993"}")` تُرجع السلسلة `9007199254740993`، مع الحفاظ على كل حرف، و`JSON.stringify` تُصدر تلك الأرقام دون تغيير داخل علامات الاقتباس. وهذا هو السبب في أن التحقق من صحة بناء الجملة وحده لا يمكنه حماية المعرف الرقمي. قارن المدخلات والمخرجات كلما ظهرت أعداد صحيحة طويلة، وتعامل مع المعرفات كسلاسل عند حدود الإنتاج عندما لا يكون الحساب جزءًا من معناها.

ما يقوله RFC 8259 عن الأرقام

RFC 8259 يحدد تهجئة الرقم JSON ولكنه لا يمنح كل تطبيق نوعًا رقميًا دقيقًا. تسمح القواعد النحوية بعلامة الطرح الاختيارية، وجزء صحيح، وأجزاء اختيارية للكسر والأس. وهو يستبعد وسائل الراحة مثل التدوين السداسي العشري، `NaN` و`Infinity`. وبالتالي، فإن `9007199254740993` صالح من الناحية النحوية على الرغم من أن مستهلك JavaScript المشترك لا يمكنه تمثيل هذا العدد الصحيح كرقم تمامًا.

إن إرشادات قابلية التشغيل البيني الخاصة بالمواصفات هي تحذير عملي: يستخدم البرنامج عادةً IEEE 754 أرقام ثنائية 64، والأعداد الصحيحة في النطاق من السالب `2^53 + 1` إلى `2^53 - 1` الموجب قابلة للتشغيل البيني بمعنى الاتفاق التام. يمكن للمدقق قبول رمز مميز أكبر بشكل صحيح بينما يقوم المحلل اللغوي بتقريبه لاحقًا.

من أين يأتي 2^53

يأتي الحد `2^53` من الدقة المتوفرة في الدلالة الثنائية 64. يعرض JavaScript أعلى عدد صحيح قابل للتمثيل على التوالي مثل `Number.MAX_SAFE_INTEGER`، وهو `9007199254740991`. عند هذا المقدار أو أقل منه، يمكن تمثيل الأعداد الصحيحة المتجاورة بشكل واضح. وفوقه، تزداد المسافة بين القيم القابلة للتمثيل، لذا فإن بعض الأعداد الصحيحة العشرية المجاورة ترتبط بالرقم نفسه. لا يقوم وقت التشغيل باقتطاع سلسلة؛ إنه تحديد أقرب قيمة متاحة بهذا التنسيق الثنائي المحدود.

فحص وحدة التحكم الكاشف هو `Number.isSafeInteger(9007199254740993)`، وهو خطأ، على الرغم من أن المصدر الحرفي قد تم تقريبه بالفعل قبل أن تتلقاه الدالة. الآخر هو `9007199254740992 === 9007199254740993`، والذي يتم تقييمه على أنه صحيح في JavaScript. تتعلق هذه الأمثلة بهوية الأعداد الصحيحة الدقيقة، وليس ما إذا كان كل رقم أكبر يصبح غير قابل للاستخدام.

كيف يفقد التحليل وإعادة التسلسل الأرقام

يتضمن تنسيق التحليل وإعادة التسلسل ثلاث مراحل: قراءة الأحرف الرقمية، وإنشاء قيمة في الذاكرة، ثم إنشاء أحرف جديدة من تلك القيمة. التفاصيل المعجمية تختفي في المرحلة المتوسطة. باستخدام `{"ticket":9223372036854775807}`، يقوم `JSON.parse` بإنشاء أقرب رقم JavaScript متاح؛ `JSON.stringify` ثم ينبعث `9223372036854776000`. لا يقوم المُسلسِل بإتلاف الرمز المميز المحفوظ بشكل مستقل. بحلول وقت التسلسل، لم يعد التسلسل الأصلي للأرقام موجودًا في الكائن الذي تم تحليله.

يستخدم تطبيق مستودع ToolAcre `JSON.parse` و`JSON.stringify`، لذلك ينطبق هذا القيد على مخرجاته المنسقة. يعمل الماسح الضوئي لبناء الجملة الخاص به لتوفير سبب وموقع ثابتين بعد فشل التحليل؛ ولا يستبدل أرقام JavaScript بتمثيل دقيق اعتباطي. وبالتالي فإن نتيجة التحقق الناجحة تؤسس قواعد نحوية، في حين أن اختلاف التنسيق يمكن أن يكشف عن فقدان الدقة.

مثال عملي: مقارنة المدخلات والمخرجات

قارن `{"numeric":9007199254740993,"text":"9007199254740993"}` قبل وبعد رحلة JavaScript ذهابًا وإيابًا. يؤدي تشغيل `JSON.stringify(JSON.parse(source), null, 2)` إلى إنشاء كائن منسق يكون عضوه `numeric` هو `9007199254740992`، بينما يظل `text` `"9007199254740993"`. كان كلا العضوين صالحين في الإدخال، وكلاهما يظل صالحًا في الإخراج. التمثيل المقتبس فقط هو الذي يحافظ على المعرف تمامًا لأنه تم فك تشفيره كبيانات أحرف بدلاً من رقم.

لا تقتصر المراجعة المفيدة على السؤال عما إذا كان المنسق يظهر باللون الأخضر. ابحث في المصدر عن تسلسلات رقمية غير منقطعة، وقارن أي قيم أطول من النطاق الآمن، وحدد ما إذا كان كل حقل يمثل كمية أو تسمية غير شفافة. إذا كان المنتج يتحكم في العقد، فقم بتغيير الملصق إلى سلسلة هناك وقم بتوثيق هذا الاختيار للمستهلكين.

حماية المعرفات في المصدر

قم بحماية المعرفات في المصدر عن طريق تعريفها كسلاسل في المخطط وإجراء تسلسل لها كسلاسل قبل أن يتلقى أي عميل JavaScript الحمولة. قد يحتوي المعرف على أرقام فقط ولا يزال غير رقمي في المعنى: لا تعد عمليات الجمع والتقريب والترتيب حسب الحجم عمليات مشروعة على مفتاح الحساب. تحافظ السلسلة أيضًا على الأصفار البادئة، والتي قد يتجاهلها التمثيل الرقمي حتى عندما يكون حجمها ضمن النطاق الآمن.

لا تستنتج الأمان عبر اللغات من حقيقة أن وقت تشغيل آخر يمكن أن يحتوي على عدد صحيح أكبر. يختلف المحللون والأنواع المستهدفة، ويمكن للوسيط المكتوب باللغة JavaScript تقريب القيمة قبل أن تراها خدمة لاحقة. يحتفظ بعض المحللين المتخصصين برموز الأرقام أو ينشئون أعدادًا صحيحة كبيرة، ولكن يجب على كل مشارك مشاركة هذا العقد.

ما لا يغطيه هذا

ما لا يغطيه هذا هو التصميم الأوسع للحساب العشري. القيم مثل `0.1` لها سلوك الفاصلة العائمة الثنائية الخاصة بها، وقد يتطلب المال أعدادًا صحيحة متدرجة أو أنواعًا عشرية وفقًا لعقد التطبيق. ولا يؤدي نقل كل رقم تلقائيًا إلى تحسين المخطط. غالبًا ما تكون التعدادات والإحداثيات والقياسات رقمية بشكل شرعي. يعتمد القرار على ما إذا كان التهجئة العشرية الدقيقة أو الهوية الصحيحة الدقيقة يجب أن تظل موجودة عند كل مستهلك في مسار البيانات.

لا تدعي هذه المناقشة أيضًا أن JSON نفسه قام بتقريب الرمز المميز أو أن جميع المحللين يتصرفون مثل JavaScript. دليل المستودع الملموس أضيق: يستدعي هذا المنسق `JSON.parse` و`JSON.stringify`، لذا فإن JavaScript تحكم دلالات الأرقام القيم غير المقتبسة هنا. يمكن لمكتبة JSON ذات الدقة العشوائية أن تقوم باختيارات مختلفة، ولكن يجب أن تحدد كيفية عرض القيم وتسلسلها.

الوجبات الجاهزة: الأرقام أعلاه 2^53 تنتمي إلى سلاسل

الوجبات الجاهزة محددة: معرفات الأعداد الصحيحة خارج النطاق الآمن لـ JavaScript تنتمي إلى سلاسل عندما يجب أن تمر عبر JavaScript دون تغيير. `9007199254740993` كرقم JSON هو بناء جملة صالح ولكنه يصبح `9007199254740992` بعد `JSON.parse`؛ `"9007199254740993"` يظل دقيقًا. الاقتباسات ليست زخرفة. إنهم يختارون تمثيلاً يحافظ على الأرقام كبيانات ويمنع المستهلكين من التعامل مع الملصق غير الشفاف ككمية تقريبية.

قبل استبدال مستند بمخرجات المنسق، قم بمقارنة الأرقام الطويلة بالأصل وتحقق من كل رقم تم تغييره. قم بإصلاح المنتج والمخطط عندما يكون ذلك ممكنًا حتى يتلقى جميع العملاء النهائيين النموذج الآمن باستمرار. يمكن أن يعرض ToolAcre النتيجة لأن مخرجاته تعكس قيمة JavaScript التي تم تحليلها، لكن لا يمكنه إعادة بناء الأرقام المفقودة بالفعل أثناء التحليل.