Українська

Інструменти розробника · JSON форматування & реаніматор

Великий цілих ідентифікаторів в JSONГоловна JavaScript формати можуть закруглювати їх

· Чому це питання

Опубліковано ToolAcre · Редакція журналу

свінгери розробник-workflow введення

Великий цілих ідентифікаторів в JSONГоловна JavaScript формати можуть закруглювати їх ілюстрованими JSON токени і точний контрольний ліміт
Головна ToolAcre векторна ілюстрація

JSON дозволяє цілям будь-якого розміру, але JavaScript є числом як 64-bit floats, так що все вище 2^53 може змінюватися при парсеріалізованій і повторній дії. Цей пост пояснює ліміт, як помітити пошкодження, і як захистити ID.

Ідентифікатор, який змінився на одному

Ідентифікатор, який змінився одним часто прибуває, як відмінно діє 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`, яка оцінює true в JavaScript. Ці приклади стосуються точної цілої ідентичності, якщо кожен більший номер стає непридатним.

Як парсеріаліз втрачає цифри

Форматування Parse-and-reserialize має три етапи: читати нумерні символи, створити незрівнянне значення, потім генерувати свіжі символи з цього значення. Лексичні деталі зникають на середній стадії. З `{"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"`. Обидва члени були дійсні в вході, і обидва залишаються дійсними у виході. Тільки процитоване представлення зберігає ідентифікатор, тому що він декодується як дані символів, а не номеру.

Корисний огляд не просто запитати, чи показаний формат зелені. Визначте джерело для неперервних послідовностей цифр, порівнюйте будь-які значення довше, ніж безпечний діапазон, і визначте, чи є кожен поле, що представляє собою кількість або знак опака. Якщо виробник контролює контракт, змініть етикетку на рядок там і документ, який вибір для споживачів.

Захист ID на джерело

Захистіть ідентифікатори на джерело, визначивши їх як рядки в схемі та послідовно їх, як рядки перед будь-яким JavaScript Клієнт отримує оплату. Ідентифікатор може містити лише цифри і все ще не менші за значенням: додавання, округлення та замовлення за величиною не є законними операціями на ключі облікового запису. А рядок також зберігає провідні нулі, які негабаритні уявлення будуть відхиляти навіть коли його величина знаходиться в межах безпечного діапазону.

Чи не заважати крос-мову безпеку від того, що інший робочий час може тримати більший ціле. Парсери і типи цілей різняться, і посередництво, написане в JavaScript може закруглити значення до пізнішого сервісу. Деякі спеціалізовані парсери зберігають кількість токени або будують великі цілі, але кожен учасник повинен поділитися цим контрактом.

Що це не криється

Що це не кришка - більш широкий дизайн десяткового арифметизму. Значення, такі як `0.1` мати власну бінарну плавучу-точкову поведінку, і гроші можуть вимагати масштабованих цілих або десяткових типів за договором програми. Нор, що говорить про те, що кожен номер автоматично покращує схему. Часто законно нумерні. Рішення залежить від того, чи точну десяткову форму або точну цілу ідентичність повинна вижити кожного споживача в шляхі даних.

Ця дискусія також не стверджує, що JSON сам закруглений токен або що всі парсери поважають, як JavaScript. Конкретні репозиторійні докази вузькі: це форматування дзвінків `JSON.parse` і `JSON.stringify`й JavaScript Кількість семантика регулюють нецитовані значення тут. Довільна оцінка JSON Бібліотека може зробити різні варіанти, але вона повинна визначити, як відображаються значення і послідовно.

Приймати: номери вище 2^53 належать в рядках

The Takeaway є специфічним: цілих ідентифікаторів зовні JavaScript’Безпека в рядках, коли вони повинні проходити через JavaScript без зміни. `9007199254740993` як JSON номер дійсний синтаксис, але стає `9007199254740992` після `JSON.parse`; `"9007199254740993"` залишається точно. Куртки не прикраса. Підберіть репрезентацію, яка зберігає цифри як дані і запобігає споживачам від обробки етикетки опаку як приблизну кількість.

Перед тим як замінити документ з вихідним форматом, порівнювати довгі числа проти оригінального і вивчити кожну змінну цифру. Виправити виробника та схему, коли це можливо, так що всі клієнти з потоку отримують безпечну форму. ToolAcre може призвести до того, що його вихід відображає JavaScript значення, але не можна реконструювати цифри, які вже втратили під час парсингу.