Перейти к содержимому
Все статьи
Разработка

У длинного ID в JSON меняются последние цифры: где потеря

·27 октября 2026 г.· 6 мин чтения
Сколько будет стоить ваш проект?Рассчитать стоимость

Если у длинного ID в JSON меняются последние цифры, сравните исходный ответ с результатом разбора: JavaScript Number может не сохранить такое целое точно. Для идентификатора обычно нужен согласованный строковый контракт на всём пути. Преобразование уже изменённого числа в строку не восстановит исходные цифры, если первоначальное представление больше не сохранено.

Сначала отличите повреждение от сокращения на экране

Показанный номер может быть визуально сокращён, выведен в экспоненциальной форме или действительно изменён. Проверьте значение и тип в конкретной точке процесса, не делая вывод по одной ячейке таблицы. В диагностике используйте вымышленный идентификатор: реальные номера клиентов и действующие запросы для этого не нужны.

Проследите исходный текст ответа, результат парсера, состояние формы и обратное сохранение. Если в первом тексте цифры ещё верны, а сразу после разбора уже отличаются, оформление таблицы не является первым местом потери. Если проблема появилась раньше, разбирать нужно и серверное представление. У веб-приложения это один сквозной контракт, а не отдельная настройка поля.

Граница безопасного целого не равна границе любого числа

По MDN Number.MAX_SAFE_INTEGER максимальное безопасное целое равно 9007199254740991, то есть 2^53−1. Речь о точном представлении и сравнении целых в безопасной области. Это не максимальное конечное значение Number и не утверждение, что каждое большее число обязательно изменится одинаковым способом.

Для идентификаторов особенно неприятно, что разные исходные значения могут стать равны. Потеряется не только красивый вывод: поиск, сравнение, ключи списка и обновление записи начнут ссылаться на неоднозначное представление. Восстановление всех цифр должно быть требованием к данным до использования, а не исправлением подписи в конце.

Проверенный учебный идентификатор

Возьмём вымышленное значение 9007199254740993. В малом локальном прогоне текущего Node числовой JSON с таким ID после JSON.parse дал 9007199254740992. Другой исходный ID 9007199254740992 стал тем же числом. Строковый вариант «9007199254740993» сохранил все знаки. Это проверка конкретного примера, не реальные данные сервиса.

ЭтапУчебное представлениеЧто получилосьСохранились исходные цифрыВывод для контракта
Исходный числовой JSONid как число 9007199254740993В тексте ответа ещё нужные цифрыНа этом этапе даСинтаксически полученный текст не доказывает безопасный разбор клиентом
Обычный JSON.parseТо же числовое полеNumber со значением 9007199254740992НетПотеря уже произошла до отображения
String после этого разбораИзменённое NumberСтрока 9007199254740992НетПозднее изменение типа не возвращает источник
Согласованное строковое полеid как строка 9007199254740993Та же строка после разбораДа в проверенном прогонеСохранить этот тип в следующих слоях
Отправка строкового поля обратноСтрока после состояния и сериализацииСтрока с теми же цифрамиДа в проверенном циклеПроверять и получателя, а не только первый парсер

Идентификатор не обязан участвовать в арифметике

Если значение нужно для связи с записью, поиска точного совпадения и передачи партнёру, числовое представление может не давать пользы. Строка также сохраняет ведущие нули, если они имеют смысл в выбранной системе. В учебном прогоне строка 000312 осталась 000312; перевод в число по другой политике изменил бы её представление.

Согласуйте допустимые символы, длину и правила сравнения. Не обрезайте пробелы, не удаляйте префиксы и не меняйте регистр без понятного договора. Сортировка текстовых идентификаторов и вычисления над количеством — разные задачи. Не превращайте любые похожие на цифры поля в Number одним общим преобразованием импортера.

Где строка снова становится числом

Проверьте клиентский адаптер, схему формы, промежуточную модель и сериализатор. Даже если сервер уже отправляет строку, библиотека или собственный код могут привести её к числу. Особенно внимательно исследуйте универсальные нормализаторы и справочники, где типы угадываются по содержимому. Уберите угадывание там, где контракт уже определён.

На интеграции через API тип должен совпадать у отправителя и получателя. Если одна сторона принимает только число, изменение клиента в одиночку может не решить проблему. Согласуйте новую схему и совместимость действующих потребителей. Старые повреждённые значения нельзя автоматически считать восстановленными после исправления будущих ответов.

Что может и чего не может reviver

Документация JSON.parse отмечает, что обычный разбор чисел происходит до вызова reviver. Поэтому String(value) для уже округлённого значения не извлекает исходный текст. Описан и специальный путь с context.source, позволяющим обратиться к исходному фрагменту; его поддержку и обработку нужно проверять в выбранной реализации.

Не смешивайте эти механизмы в обещании «reviver всегда спасёт». Если проект выбирает BigInt или специализированный парсер, согласуйте также хранение, сериализацию и обмен с остальными слоями. Это отдельный технический договор. Для текстовой идентичности основной строковый контракт часто проще объяснить и проверить, когда обе стороны могут его поддержать.

Приёмка всей цепочки

  1. Подготовьте вымышленные идентификаторы: обычный, граничный, два различающихся длинных значения и строку с ведущими нулями. Сохраните ожидаемый текст отдельно.
  2. Сравните сырой ответ и результат разбора, фиксируя значение вместе с типом. Найдите первое необратимое преобразование.
  3. Пройдите состояние формы, поиск и сравнение. Два разных учебных ID должны оставаться разными по согласованному контракту.
  4. Сохраните запись и разберите обратный результат. Проверяйте все цифры, а не длину подписи или округлённый вывод.
  5. Повторите обмен через применимые интеграции и импорт. Отдельно испытайте недопустимый тип, вместо молчаливой коррекции.
  6. Определите порядок разбора уже повреждённых записей по авторитетному источнику. Не восстанавливайте последние цифры догадкой.

При переносе данных в CRM зафиксируйте, какой источник считается исходным и как подтверждается соответствие. Удачный новый тест не доказывает чистоту старой базы. Результат исправления должен включать сохранённый тип, неизменность идентичности и понятную процедуру для прежних расхождений.

Вопросы и ответы

Что означает Number.MAX_SAFE_INTEGER?

Это граница безопасных целых для Number, равная 9007199254740991. Её нельзя путать с максимальным конечным значением типа или трактовать как одинаковое округление всех больших чисел.

Как передавать длинный ID при JSON.parse и BigInt?

Сначала согласуйте представление на стороне отправителя, например строковый идентификатор. Если выбран специальный парсер или BigInt, отдельно проверьте весь путь хранения и обратной сериализации.

Чем MAX_SAFE_INTEGER отличается от MAX_VALUE?

Первое относится к безопасности целочисленного представления и сравнения, второе — к максимальному конечному значению Number. Возможность хранить большое число ещё не означает сохранность всех цифр идентификатора.

Нужна помощь с проектом?

Обсудим задачу и предложим решение — от сайта до SaaS и защиты.

Связаться