JSON Toolkit

Wyszukiwanie komunikatów błędów JSON: od tekstu błędu prosto do poprawki

Podsumowanie: Znajdź przyczynę po dokładnym komunikacie JSON.parse: 12 częstych błędów w Chrome, Firefoksie i Safari, w tym strony błędów HTML, obcięcie i podwójne parsowanie.

Zaawansowany~8 min czytaniaOpublikowano 2026-10-30Zaktualizowano 2026-11-04
Okładka tabeli wyszukiwania komunikatów błędów JSON

Najważniejsze: gdy pojawi się błąd JSON.parse, najpierw weź position i token; position 0 oznacza sprawdzenie odpowiedzi HTML, BOM lub złego typu, a komunikat „Expected” oznacza sprawdzenie poprzedzającego znaku — nie czytaj od nowa wiersz po wierszu od zgłoszonego położenia.

Tekst błędu to nie szum — to odpowiedź. Parser mówi, na który znak trafił, czego oczekiwał i co faktycznie dostał. Szukanie po komunikacie błędu jest lepsze niż przepisywanie całego dokumentu ręcznie.

Każdy błąd JSON.parse() ma trzy części: position (przesunięcie znaku lub wiersz/kolumna), oczekiwanie (Expected...) i rzeczywistość (Unexpected token X albo xxx is not valid JSON). Silniki formułują je różnie — Chrome i Node (V8) mówią Expected ',' or '}' after property value in JSON at position 25, Firefox mówi JSON.parse: expected ',' or '}' after property value in object at line 3 column 1, Safari mówi JSON Parse error: Expected ',' or '}' — ale wszystkie trzy wskazują to samo pęknięcie składni. Szukając błędu, ignoruj sformułowanie i wyciągnij trzy fakty: który znak, czego oczekiwano, co przyszło.

1. Tabela wyszukiwania 12 błędów

Lewa kolumna zawiera najbardziej rozpoznawalny fragment z konsoli (sformułowanie V8). Warianty Firefoksa/Safari podano w nawiasach.

Tekst błędu (V8) Prawdziwa przyczyna Poprawka
Unexpected token < in JSON at position 0 API zwróciło HTML (stronę 404, szablon 500, przekierowanie logowania, fallback proxy), a nie JSON Najpierw sprawdź response.status i Content-Type; nie poprawiaj JSON-a
Unexpected end of JSON input Dane wejściowe są puste lub obcięte: puste ciało, 204, przerwane pobieranie, kopia bez ostatniego wiersza Obsłuż przypadek pusty, porównaj Content-Length, aby znaleźć cięcie
Unexpected token o / "[object Object]" is not valid JSON Do JSON.parse() ponownie przekazano już sparsowany obiekt, który został przekształcony w łańcuch Sprawdź typeof; jeśli to obiekt, użyj go bezpośrednio
"undefined" is not valid JSON Zmiennej nigdy nie przypisano (JSON.parse(undefined)) Zainicjuj wartości zapasowe; chroń się przed parsowaniem
Expected double-quoted property name in JSON Przecinek końcowy ({"a": 1,}); parser oczekuje kolejnego klucza i napotyka } Usuń przecinek po ostatnim elemencie
Expected property name or '}' in JSON Klucz bez cudzysłowów lub w pojedynczych cudzysłowach ({name: "Ada"}, {'name': 'Ada'}) Ujmij każdy klucz w podwójne cudzysłowy
Expected ',' or '}' after property value in JSON Brakujący przecinek ({"a": 1 "b": 2}) lub komentarz po wartości Dodaj przecinek; usuń komentarz
Unexpected token '/' Komentarz // lub /* */ wewnątrz JSON Usuń go albo parsuj konfigurację jako JSONC
Bad control character in string literal Surowy znak nowej linii, tabulator lub inny znak sterujący U+0000–U+001F wewnątrz łańcucha Zapisz \n; generuj przez JSON.stringify
Unterminated string in JSON Łańcuch otwarty " i nigdy nie zamknięty albo nieescape'owany cudzysłów wewnętrzny Escape'uj wewnętrzne cudzysłowy jako \"
Unexpected non-whitespace character after JSON Dwa dokumenty w jednym tekście: {}{}, NDJSON, opakowanie JSONP Podziel po wierszach i parsuj każdy, albo użyj parsera NDJSON
JSON.parse is not a function Własna zmienna przesłania globalny JSON Zmień nazwę zmiennej; nigdy nie nazywaj jej JSON

Dwa pierwsze zasługują na bliższe spojrzenie, ponieważ żaden nie znaczy „twój JSON jest zły” — znaczą „to, co otrzymałeś, nie jest tym, co myślisz”.

2. Trzy częste źródła błędu position 0

Position 0 oznacza, że pierwszy znak jest nielegalny. Jeśli nic nie wygląda podejrzanie, znak prawdopodobnie jest niewidoczny. Trzej zwykli podejrzani:

Pierwszy: <, czyli HTML. To najczęstszy błąd parsowania w produkcji. Zły URL, wygasła sesja przekierowana przez bramkę albo szablon błędu serwera — ciało zaczyna się od <!DOCTYPE html> i parser rezygnuje na pierwszym znaku. Właściwym krokiem jest otwarcie panelu sieci i odczytanie surowej odpowiedzi, a potem poprawa wywołania API, a nie JSON-a.

Drugi: BOM lub znaki zerowej szerokości. Pliki zapisane przez Notatnik w Windows często zaczynają się od BOM UTF-8 (\uFEFF), a tekst skopiowany ze stron internetowych lub komunikatorów może nieść spacje zerowej szerokości (\u200B–\u200D). Niewidoczne dla ciebie, oczywiste dla parsera:

// Strip BOM and zero-width characters before parsing
const cleaned = raw.replace(/^\uFEFF/, '').replace(/[\u200B-\u200D]/g, '');
const data = JSON.parse(cleaned);

Trzeci: zły typ. JSON.parse(undefined) zgłasza "undefined" is not valid JSON; JSON.parse(someObject) zgłasza Unexpected token o (obiekt został przekształcony w "[object Object]", a o jest nielegalne na pozycji 1). Oba znaczą „dane są już sparsowane” albo „nigdy nie było żadnych danych”. Sprawdź typ, a nie składnię:

let data = text;
if (typeof data === 'string') {
  data = JSON.parse(data); // Parse only when it really is a string
}

3. Position wskazuje niżej; przyczyna jest wyżej

Dwa błędy wprowadzają w błąd co do położenia i są to dwa najczęściej błędnie odczytywane wpisy w tabeli:

  • Brakujący przecinek: {"a": 1 "b": 2} zgłasza Expected ',' or '}' after property value w wierszu "b". Zgłoszenie jest poprawne, ale poprawka należy na koniec poprzedniego wiersza.
  • Brakujący nawias zamykający: głębokie zagnieżdżenie bez jednego } lub ] sprawia, że parser połyka wszystko do końca wejścia i zgłasza Unexpected end of JSON input. Position to koniec pliku; prawdziwa luka może być znacznie wcześniej. Szukaj wstecz najświeższego niezamkniętego { lub [ — liczenie par bije wpatrywanie się.

Ogólna technika to bisekcja: odetnij tekst przed zgłoszonym położeniem i sparsuj go osobno. Jeśli się parsuje, problem jest blisko zgłoszonego położenia; jeśli nie, bisekcjonuj dalej wstecz. Granica pierwszego zawodzącego fragmentu jest prawdziwym miejscem błędu. Przy dużych plikach najpierw sformatuj dokument — przy wyrównanych wcięciach brakujący poziom widać na pierwszy rzut oka (online formater JSON dobrze się do tego nadaje).

4. Cztery „fałszywie zdrowe” stany, które parsują się dobrze, ale zachowują źle

Gorszy niż błąd jest brak błędu i złe dane. We wszystkich czterech przypadkach JSON jest poprawny, a parser zadowolony — problemem jest kształt danych:

  1. Podwójne kodowanie: cały dokument został JSON.stringify-owany dwukrotnie, więc parsowanie zwraca łańcuch, a nie obiekt. Jeśli typeof result === 'string', sparsuj ponownie — ale znajdź i napraw podwójną serializację u źródła.
  2. Zduplikowane klucze po cichu nadpisują: {"name": "Tom", "name": "Jerry"} jest poprawnym JSON-em, większość parserów nie zgłasza zastrzeżeń, a wygrywa druga wartość. To gryzie przy scalaniu danych z kilku źródeł; ujawnij to ścisłym walidatorem JSON, zanim ugryzie.
  3. NDJSON potraktowany jako jeden dokument: strumieniowe API emitują jeden obiekt na wiersz; parsowanie całego tekstu zawodzi z Unexpected non-whitespace character after JSON. Podziel po \n i parsuj wiersz po wierszu.
  4. Cicha utrata precyzji liczb: liczby całkowite powyżej 2^53 - 1 (identyfikatory snowflake) wracają z wyzerowanymi ostatnimi cyframi, całkiem bez błędu. Przesyłaj identyfikatory jako łańcuchy.

Wspólny wątek: parser uważa, że wszystko jest w porządku. Dlatego gdy dane z API wyglądają źle, najpierw wypisz pierwsze 80 znaków surowego tekstu i jego typeof — potwierdź kształt, zanim zaczniesz omawiać treść.

5. Uczyń błędy niemożliwymi już przy zapisie

Tabela wyszukiwania to narzędzie po fakcie; zapobieganie to narzędzie przed faktem. Cztery nawyki przechwytują większość błędów, zanim wystąpią:

// 1. Two checks before parsing any response
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() already parses — do not parse again
  • Generuj przez serializację, nigdy przez sklejanie: JSON.stringify() poprawnie obsługuje cudzysłowy, znaki nowej linii i znaki sterujące; ręcznie budowane łańcuchy to główne źródło Bad control character i Unterminated string.
  • Zawsze przechwytuj: zgłoszony błąd JSON.parse to synchroniczna awaria, chyba że coś go przechwyci. Przy niezaufanych danych wejściowych — localStorage, plikach zewnętrznych — blok catch potrzebuje wartości domyślnej lub jawnego zgłoszenia błędu.
  • Oddaj strukturę schematowi: poprawna składnia nie znaczy poprawna struktura. Brakujące pola i złe typy należą do walidacji JSON Schema na granicy; zobacz co rozwiązuje JSON Schema.

6. Szybka ścieżka decyzyjna

Ściśnij cały artykuł w jeden porządek decyzyjny. Widząc błąd, najpierw weź position i token:

  1. Position 0 → sprawdź trzy źródła: < (HTML), BOM, zły typ;
  2. end of input → sprawdź puste lub obcięte ciało, a następnie szukaj wstecz niezamkniętych nawiasów;
  3. Expected ... → popatrz na poprzedzający znak; to zwykle brakujący przecinek lub cudzysłów;
  4. after JSON data → sklejono wiele dokumentów; podziel po wierszach;
  5. Parsuje się dobrze, ale dane wyglądają źle → wykonaj cztery kontrole „fałszywie zdrowych” stanów.

W połączeniu z krok po kroku triage w jak naprawić błędy parsowania JSON, 90% problemów z parsowaniem rozwiązuje się w ciągu pięciu minut. Zostaw sam tekst błędu w zakładkach — to log debugowania, który napisał dla ciebie parser, jego sformułowanie zmienia się raz na trzy lata, a jedno wyszukanie zwraca się przez rok.

Co znaczy „Unexpected token in JSON”?

Parser trafił na znak nielegalny w tym miejscu gramatyki JSON. Token to odrzucony znak: < zwykle oznacza, że API zwróciło HTML, ' oznacza pojedyncze cudzysłowy, / oznacza komentarz, a zwykła litera zwykle oznacza klucz bez cudzysłowów albo literał tylko-JavaScriptowy, taki jak undefined lub NaN. Przeczytaj najpierw token, potem position, a przyczyna zawęzi się do jednej.

Jak naprawić „Unexpected end of JSON input”?

Dwa źródła: puste dane wejściowe (puste ciało odpowiedzi albo pusty łańcuch w localStorage) lub obcięte dane wejściowe (przerwane pobieranie, kopia bez ostatniego wiersza, limit rozmiaru). Obsłuż przypadek pusty przez if (!text) return; następnie zweryfikuj kompletność i zamknij najświeższy niezamknięty {, [ lub ". Uwaga: błąd może też pochodzić z głęboko brakującego nawiasu — position przypadkiem wypada na końcu pliku.

Dlaczego Chrome, Firefox i Safari zgłaszają błędy inaczej?

Trzy przeglądarki dostarczają różne silniki JS (V8, SpiderMonkey, JavaScriptCore), a każdy formułuje błędy po swojemu; MDN dokumentuje wszystkie oficjalne warianty. Ale wszystkie trzy błędy niosą te same trzy elementy — position, oczekiwanie, rzeczywistość — o semantyce jeden do jednego. Przetłumacz na sformułowanie V8 i używaj tej tabeli bez zmian.

Position błędu wskazuje miejsce, które wygląda dobrze — co teraz?

Prawdziwy błąd jest wcześniej. Typowe przypadki: brakujący przecinek (zgłoszony w następnym wierszu) i brakujący nawias zamykający (zgłoszony na końcu pliku). Idź wstecz od zgłoszonego położenia token po tokenie albo stosuj bisekcję: sparsuj samą pierwszą połowę, a granica pierwszego zawodzącego fragmentu będzie prawdziwym miejscem błędu.