CodeKitHub
Polski
Napraw "Unexpected token" w JSON.parse: przewodnik po każdej przyczynie

Napraw "Unexpected token" w JSON.parse: przewodnik po każdej przyczynie

Opublikowano 23 lip 2026

SyntaxError: Unexpected token X in JSON at position N to jeden z najczęstszych błędów w JavaScript i jeden z najmniej pomocnych — mówi gdzie parser się poddał, a nie dlaczego. Oto jak faktycznie go naprawić.

Krok 1: odczytaj numer pozycji

JSON.parse liczy znaki od początku ciągu, zaczynając od 0. Jeśli twój JSON pochodzi ze zmiennej, zaloguj dokładny fragment wokół tej pozycji, zanim zrobisz cokolwiek innego:

try {
  JSON.parse(raw);
} catch (e) {
  const match = e.message.match(/position (\d+)/);
  if (match) {
    const pos = Number(match[1]);
    console.log(raw.slice(Math.max(0, pos - 20), pos + 20));
  }
}

Ten jeden fragment kodu rozwiązuje więcej takich błędów niż jakakolwiek rada dotycząca składni JSON, ponieważ większość błędów „unexpected token” to tak naprawdę błędy „nie wiem, co naprawdę zawiera mój ciąg” — końcowe białe znaki z kopiuj-wklej, dodatkowy znak nowej linii z literału szablonu albo znacznik kolejności bajtów (BOM) na samym początku (pozycja 0, token , niewidoczny w większości edytorów).

7 przyczyn, uszeregowanych według częstości występowania

  1. Przecinek końcowy. {"a": 1, "b": 2,} — poprawne w literałach obiektów JS, niepoprawne w JSON. Przecinek przed } lub ] to zdecydowanie najczęstsza przyczyna.
  2. Pojedyncze cudzysłowy zamiast podwójnych. {'a': 1} to JS, nie JSON. JSON wymaga podwójnych cudzysłowów zarówno wokół kluczy, jak i wartości tekstowych, bez wyjątków.
  3. Klucze bez cudzysłowów. {a: 1} — znów poprawne w JS, niepoprawne w JSON. Każdy klucz potrzebuje cudzysłowów.
  4. Wartość JS, która nie jest poprawnym JSON. undefined, NaN, funkcja lub komentarz (// tak jak ten) — żadne z nich nie istnieje w specyfikacji JSON, tylko w JavaScript.
  5. Podwójne kodowanie. Wywołałeś JSON.stringify() dwukrotnie albo parsujesz ciąg, który już jest obiektem — sprawdź typeof raw === 'string' przed wywołaniem .parse().
  6. Pusty ciąg lub odpowiedź undefined. Jeśli fetch zakończył się cicho niepowodzeniem albo zwrócił pustą treść, JSON.parse("") rzuca Unexpected end of JSON input, inny, ale powiązany błąd — sprawdź response.ok i zaloguj surową treść przed parsowaniem.
  7. BOM lub niewidoczne znaki z kopiuj-wklej. Wklejenie JSON z PDF-a, dokumentu Word lub jakiegoś wyjścia terminala może przenieść BOM lub twardą spację, która wygląda identycznie jak normalny znak.

Najszybsza naprawa: waliduj przed debugowaniem

Odczytywanie surowych komunikatów błędów znak po znaku jest wolne. Wklej dokładny ciąg do formatera, który podświetla nieprawidłowy znak bezpośrednio, zamiast zgadywać na podstawie numeru pozycji — zamienia to „gdzieś w pobliżu znaku 812” w „ten konkretny brakujący nawias, dokładnie tutaj”. (Link poniżej.)

Gdy JSON jest naprawdę poprawny, a mimo to zawodzi

Jeśli formater potwierdza, że twój JSON jest poprawny składniowo, a JSON.parse nadal rzuca błąd, ciąg, który przekazujesz, nie jest tym ciągiem, o którym myślisz. Najczęstszy powód: wywołujesz .parse() na obiekcie Response zamiast na jego rozwiązanej treści.

// Źle — parsuje "[object Response]", nie treść
const data = JSON.parse(await fetch(url));

// Dobrze
const data = await (await fetch(url)).json();
// albo, jeśli najpierw potrzebujesz surowego tekstu:
const text = await (await fetch(url)).text();
const data = JSON.parse(text);

Szybka ściągawka

Objaw Prawdopodobna przyczyna
Unexpected token } Przecinek końcowy przed zamykającym nawiasem klamrowym
Unexpected token ' Użyto pojedynczych cudzysłowów zamiast podwójnych
Unexpected token a (lub dowolna litera) Klucz obiektu bez cudzysłowów
Unexpected end of JSON input Pusty ciąg, ucięta odpowiedź lub niezamknięty nawias
Unexpected token  (pozycja 0) Znacznik kolejności bajtów ze skopiowanego lub zapisanego w Windows pliku

Żadne z nich nie wymaga niczego na pamięć — naprawa to zawsze te same trzy kroki: zaloguj fragment wokół zgłoszonej pozycji, przepuść go przez formater, popraw jeden znak, który zostanie oznaczony.

← Powrót do bloga