JSON Toolkit

Довідник повідомлень про помилки JSON: від тексту помилки просто до виправлення

Головне: Знаходьте причину за точним повідомленням JSON.parse: 12 частих помилок у Chrome, Firefox і Safari, зокрема HTML-сторінки помилок, обрізання й подвійний розбір.

Просунутий~8 хв читанняОпубліковано 2026-10-30Оновлено 2026-11-04
Обкладинка таблиці-довідника повідомлень про помилки JSON

Коротко: коли з'являється помилка JSON.parse, спершу схопіть позицію й токен; позиція 0 означає перевірку на HTML-відповідь, BOM чи неправильний тип, а повідомлення «Expected» означає, що треба дивитися на попередній символ — не перечитуйте рядок за рядком від вказаної позиції.

Текст помилки — це не шум, а відповідь. Парсер каже, на який символ натрапив, чого очікував і що насправді отримав. Пошук за повідомленням про помилку краще за ручне переписування всього документа.

Кожна помилка JSON.parse() складається з трьох частин: позиція (відступ символу або рядок/стовпець), очікування (Expected...) і реальність (Unexpected token X або xxx is not valid JSON). Рушії формулюють їх по-різному — Chrome і Node (V8) кажуть Expected ',' or '}' after property value in JSON at position 25, Firefox каже JSON.parse: expected ',' or '}' after property value in object at line 3 column 1, Safari каже JSON Parse error: Expected ',' or '}' — але всі три вказують на той самий синтаксичний злам. Коли шукаєте помилку, ігноруйте формулювання й схопіть три факти: який символ, чого очікували, що надійшло.

1. Таблиця 12 помилок

Ліва колонка — найбільш упізнаваний фрагмент із вашої консолі (формулювання V8). Варіанти Firefox/Safari — у дужках.

Текст помилки (V8) Справжня причина Виправлення
Unexpected token < in JSON at position 0 API повернув HTML (сторінку 404, шаблон 500, перенаправлення на логін, запасний варіант проксі), а не JSON Спершу перевірте response.status і Content-Type; не виправляйте JSON
Unexpected end of JSON input Вхід порожній або обрізаний: порожнє тіло, 204, перерване завантаження, копія без останнього рядка Обробіть порожній випадок, порівняйте Content-Length, щоб знайти обріз
Unexpected token o / "[object Object]" is not valid JSON Уже розібраний об'єкт знову передали в JSON.parse() і приведено до рядка Перевірте typeof; якщо це об'єкт, використовуйте його безпосередньо
"undefined" is not valid JSON Змінній ніколи не присвоювали значення (JSON.parse(undefined)) Ініціалізуйте резервні значення; перевіряйте перед розбором
Expected double-quoted property name in JSON Висяча кома ({"a": 1,}); парсер очікує ще один ключ і знаходить } Видаліть кому після останнього елемента
Expected property name or '}' in JSON Ключ без лапок або в одинарних лапках ({name: "Ada"}, {'name': 'Ada'}) Беріть кожен ключ у подвійні лапки
Expected ',' or '}' after property value in JSON Пропущена кома ({"a": 1 "b": 2}) або коментар після значення Додайте кому; приберіть коментар
Unexpected token '/' Коментар // або /* */ усередині JSON Видаліть його або розбирайте конфігурацію як JSONC
Bad control character in string literal Сирий перевід рядка, табуляція чи інший керівний символ U+0000–U+001F усередині рядка Пишіть \n; генеруйте через JSON.stringify
Unterminated string in JSON Рядок відкрито лапкою " і не закрито, або внутрішню лапку не екрановано Екрануйте внутрішні лапки як \"
Unexpected non-whitespace character after JSON Два документи в одному тексті: {}{}, NDJSON, обгортка JSONP Розділіть за рядками й розбирайте кожен, або використовуйте парсер NDJSON
JSON.parse is not a function Ваша власна змінна затіняє глобальний JSON Перейменуйте змінну; ніколи не називайте її JSON

Перші дві варті ближчого погляду, бо жодна не означає «ваш JSON неправильний» — вони означають «те, що ви отримали, не те, чим ви його вважаєте».

2. Три часті джерела помилки з позицією 0

Позиція 0 означає, що найперший символ недопустимий. Якщо ніщо не виглядає підозрілим, символ, найімовірніше, невидимий. Три звичні підозрювані:

Перший: <, тобто HTML. Це найчастіша помилка розбору у виробництві. Неправильний URL, сесія, що закінчилася і була перенаправлена шлюзом, або шаблон помилки сервера — тіло починається з <!DOCTYPE html>, і парсер здається на першому ж символі. Правильний крок — відкрити панель Network і прочитати сиру відповідь, а потім виправити виклик API, а не JSON.

Другий: BOM або символи нульової ширини. Файли, збережені Windows Notepad, часто починаються з BOM UTF-8 (\uFEFF), а текст, копійований зі сторінок або чатів, може містити пробіли нульової ширини (\u200B–\u200D). Для вас невидимі, для парсера очевидні:

// Прибрати BOM і символи нульової ширини перед розбором
const cleaned = raw.replace(/^\uFEFF/, '').replace(/[\u200B-\u200D]/g, '');
const data = JSON.parse(cleaned);

Третій: неправильний тип. JSON.parse(undefined) повідомляє "undefined" is not valid JSON; JSON.parse(someObject) повідомляє Unexpected token o (об'єкт приведено до "[object Object]", а o недопустимий на позиції 1). Обидва означають «дані вже розібрані» або «даних ніколи не було». Перевіряйте тип, а не синтаксис:

let data = text;
if (typeof data === 'string') {
  data = JSON.parse(data); // Розбирайте, лише коли це справді рядок
}

3. Позиція вказує нижче за течією, а причина — вище

Дві помилки вводять в оману щодо місця, і це два найбільш неправильно прочитані записи таблиці:

  • Пропущена кома: {"a": 1 "b": 2} повідомляє Expected ',' or '}' after property value у рядку з "b". Повідомлення правильне, але виправлення належить у кінець попереднього рядка.
  • Пропущена закривна дужка: глибока вкладеність без одного } або ] змушує парсер проковтнути все до кінця вводу й повідомити Unexpected end of JSON input. Позиція — кінець файлу; справжній розрив може бути набагато раніше. Шукайте назад найостанніший незакритий { або [ — підрахунок пар краще за вдивляння.

Загальна техніка — бісекція: відріжте текст до вказаної позиції й розберіть його окремо. Якщо розбирається, проблема близько до вказаної позиції; якщо ні — діліть далі назад. Межа першого фрагмента, що не розбирається, і є справжнім місцем помилки. Для великих файлів спершу відформатуйте документ — з вирівняними відступами пропущений рівень видно одразу (онлайн-форматувальник JSON чудово для цього підходить).

4. Чотири «хибно здорові» стани, що розбираються нормально, але поводяться неправильно

Гірше за помилку — коли помилки немає, а дані неправильні. У всіх чотирьох випадках JSON валідний, а парсер задоволений — проблема у формі даних:

  1. Подвійне кодування: весь документ було двічі оброблено JSON.stringify, тож розбір дає рядок, а не об'єкт. Якщо typeof result === 'string', розберіть ще раз — але знайдіть і виправте подвійну серіалізацію в джерелі.
  2. Повторювані ключі мовчки перезаписують: {"name": "Tom", "name": "Jerry"} — валідний JSON, більшість парсерів не скаржаться, і перемагає друге значення. Це кусає під час злиття даних із кількох джерел; виявіть це строгим валідатором JSON, перш ніж воно вкусить вас.
  3. NDJSON сприймають як один документ: потокові API видають по одному об'єкту на рядок; розбір усього тексту завершується з Unexpected non-whitespace character after JSON. Розділіть за \n і розбирайте по рядку.
  4. Тихе втрачання точності чисел: цілі числа, більші за 2^53 - 1 (ID сніжинки), повертаються із зануленими останніми цифрами, без жодної помилки. Передавайте ID як рядки.

Спільна нитка: парсер вважає, що все гаразд. Тож коли дані API виглядають неправильно, спершу виведіть перші 80 символів сирого тексту та його typeof — підтвердьте форму, перш ніж обговорювати вміст.

5. Зробіть помилки неможливими під час запису

Таблиця — інструмент після факту; профілактика — інструмент до факту. Чотири звички перехоплюють більшість помилок до того, як вони стануться:

// 1. Дві перевірки перед розбором будь-якої відповіді
const response = await fetch('/api/users');
if (!response.ok) {
  throw new Error(`HTTP ${response.status}: the API returned no data`);
}
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.includes('application/json')) {
  throw new Error(`Expected JSON, got ${contentType}`);
}
const data = await response.json(); // 2. json() уже розбирає — не розбирайте знову
  • Серіалізуйте, щоб генерувати, ніколи не склеюйте: JSON.stringify() правильно обробляє лапки, переведення рядків і керівні символи; рядки, складені вручну, — головне джерело Bad control character та Unterminated string.
  • Завжди перехоплюйте: викинута помилка JSON.parse — це синхронний збій, якщо її ніщо не перехоплює. Для недовіреного вводу — localStorage, зовнішні файли — блоку catch потрібне значення за замовчуванням або явне повідомлення про помилку.
  • Доручайте структуру схемі: валідний синтаксис не означає валідну структуру. Відсутні поля й неправильні типи належать перевірці JSON Schema на межі; дивіться що вирішує JSON Schema.

6. Швидкий шлях рішення

Стисніть усю статтю в один порядок рішень. Коли бачите помилку, спершу схопіть позицію й токен:

  1. Позиція 0 → перевірте три джерела: < (HTML), BOM, неправильний тип;
  2. end of input → перевірте порожнє чи обрізане тіло, потім пошукайте назад незакриті дужки;
  3. Expected ... → подивіться на попередній символ; зазвичай це пропущена кома або лапка;
  4. after JSON data → кілька документів склеєно; розділіть за рядком;
  5. Розбирається нормально, але дані виглядають неправильно → виконайте чотири перевірки «хибно здорових» станів.

Разом із покроковим тріажем у як виправити помилки розбору JSON 90% проблем розбору вирішуються за п'ять хвилин. Тримайте сам текст помилки в закладках — це журнал налагодження, який парсер написав для вас; його формулювання змінюється раз на три роки, і один пошук окупає рік.

Що означає «Unexpected token in JSON»?

Парсер натрапив на символ, недопустимий у цьому місці граматики JSON. Токен — це відхилений символ: < зазвичай означає, що API повернув HTML, ' означає одинарні лапки, / означає коментар, а звичайна літера зазвичай означає ключ без лапок або літерал, що існує лише в JavaScript, як-от undefined чи NaN. Прочитайте спершу токен, потім позицію, і причина звужується до однієї.

Як виправити «Unexpected end of JSON input»?

Два джерела: порожній вхід (порожнє тіло відповіді або порожній рядок у localStorage) чи обрізаний вхід (перерване завантаження, копія без останнього рядка, обмеження розміру). Обробіть порожній випадок через if (!text) return; потім перевірте повноту й закрийте найостанніший незакритий {, [ або ". Зауважте, що помилка може також походити від глибоко пропущеної дужки — позиція просто випадково збігається з кінцем файлу.

Чому Chrome, Firefox і Safari повідомляють про помилки по-різному?

Три браузери мають різні рушії JS (V8, SpiderMonkey, JavaScriptCore), і кожен формулює свої помилки по-своєму; MDN документує всі офіційні варіанти. Але всі три помилки містять ті самі три елементи — позицію, очікування, реальність — з однозначною відповідністю. Перекладіть на формулювання V8 і користуйтеся цією таблицею як є.

Позиція помилки вказує туди, де все виглядає добре — що тепер?

Справжня помилка раніше. Типові випадки: пропущена кома (повідомлена в наступному рядку) і пропущена закривна дужка (повідомлена в кінці файлу). Ідіть назад від вказаної позиції токен за токеном або діліть навпіл: розберіть першу половину окремо, і межа першого фрагмента, що не розбирається, буде справжнім місцем помилки.