Unexpected token: znak, který do JSON nepatří

Parser JSON narazil na znak, který na daném místě do syntaxe nepatří. Nejčastěji server vrátil HTML (chybovou nebo přihlašovací stránku) místo JSON a hláška pak zní Unexpected token '<', … is not valid JSON. Další častou příčinou je klíč bez uvozovek nebo apostrofy místo dvojitých uvozovek. Ty nové verze V8 hlásí jako Expected property name or '}'.

Autor: Aktualizováno

Znění hlášky v jednotlivých prostředích

Hlášky pocházejí z konkrétních parserů, nejsou to názvy chyb z normy. Stejná chyba proto v Chromu, Firefoxu, Pythonu nebo .NET zní jinak:

Parser Hláška Kdy
Node.js 25, Chrome 153 (V8) JSON.parse, response.json(), Edge a další prohlížeče s V8 Unexpected token '<', "<!DOCTYPE html>" is not valid JSON Server vrátil HTML místo JSON
Expected property name or '}' in JSON at position 1 (line 1 column 2) Klíč bez uvozovek (zápis objektu z JavaScriptu), Apostrofy místo dvojitých uvozovek
Firefox 158 JSON.parse, response.json() JSON.parse: unexpected character at line 1 column 1 of the JSON data Server vrátil HTML místo JSON
JSON.parse: expected property name or '}' at line 1 column 2 of the JSON data Klíč bez uvozovek (zápis objektu z JavaScriptu), Apostrofy místo dvojitých uvozovek
Safari (WebKit 26) JSON.parse, response.json() JSON Parse error: Unrecognized token '<' Server vrátil HTML místo JSON
JSON Parse error: Expected '}' Klíč bez uvozovek (zápis objektu z JavaScriptu)
JSON Parse error: Single quotes (') are not allowed in JSON Apostrofy místo dvojitých uvozovek
Python 3.14 json.loads, json.load (json.JSONDecodeError) Expecting value: line 1 column 1 (char 0) Server vrátil HTML místo JSON
Expecting property name enclosed in double quotes: line 1 column 2 (char 1) Klíč bez uvozovek (zápis objektu z JavaScriptu), Apostrofy místo dvojitých uvozovek
.NET 10 (System.Text.Json) JsonDocument.Parse, JsonSerializer.Deserialize '<' is an invalid start of a value. Server vrátil HTML místo JSON
'j' is an invalid start of a property name. Expected a '"'. Klíč bez uvozovek (zápis objektu z JavaScriptu)
''' is an invalid start of a property name. Expected a '"'. Apostrofy místo dvojitých uvozovek
PHP 8.4 json_last_error_msg(), JsonException s JSON_THROW_ON_ERROR Syntax error Server vrátil HTML místo JSON, Klíč bez uvozovek (zápis objektu z JavaScriptu), Apostrofy místo dvojitých uvozovek

Znak v apostrofech ('<', 'N') a pozice ukazují, kde parser skončil. Pozice 0 nebo řádek 1, sloupec 1 znamená, že vstup není JSON už od začátku. PHP hlásí u většiny syntaktických chyb jen Syntax error a místo neuvádí. Polohu najdeš ve validátoru.

Příčiny a opravy

Server vrátil HTML místo JSON

Chybně
<!DOCTYPE html>
Opraveno
{"jmeno": "Eva"}

Znak < na začátku znamená HTML: stránku 404 nebo 500, přesměrování na přihlášení, nebo vývojový server, který na neznámou cestu vrací index.html. response.json() pak selže, i když je chyba ve skutečnosti v URL nebo v oprávnění. Před čtením JSON zkontroluj stavový kód a Content-Type:

JavaScript: srozumitelná chyba místo SyntaxError
async function getJson(url) {
  const response = await fetch(url);
  const type = response.headers.get('content-type') ?? '';
  if (!response.ok || !/\bjson\b/.test(type)) {
    // Ukaž, co server doopravdy poslal, místo SyntaxError z response.json().
    throw new Error(`${response.status} ${type}: ${(await response.text()).slice(0, 200)}`);
  }
  return response.json();
}

Podmínka \bjson\b propustí application/json i typy jako application/problem+json. Typy médií pro JSON a XML jsou v referenci MIME typů.

Klíč bez uvozovek (zápis objektu z JavaScriptu)

Chybně
{jmeno: "Eva"}
Opraveno
{"jmeno": "Eva"}

JSON není zápis objektu z JavaScriptu. Názvy vlastností musí být řetězce v dvojitých uvozovkách, undefined ani komentáře nejsou povolené. Rozdíly popisuje JSON vs JavaScript.

Apostrofy místo dvojitých uvozovek

Chybně
{'jmeno':'Eva'}
Opraveno
{"jmeno":"Eva"}

Pro výrobu JSON použij serializátor (JSON.stringify, json.dumps). Globální nahrazení apostrofů zničí například jméno O’Connor nebo text s uvozovkami, oprava musí vycházet z původní datové struktury.

Jak najít příčinu

Nejprve ověř celé vstupní tělo: vypiš ho jako text, ne až jako výsledek parseru. Pokud jsi získal HTTP odpověď, zkontroluj status a Content-Type. Neopravuj nesprávný formát pomocí eval.

Přesné znění, pozice a délka hlášky závisí na parseru a verzi. Pozice obvykle označuje místo, kde parser problém odhalil, ne vždy začátek příčiny.

Neviditelný BOM a komentáře

Chybně: komentář patří například do JSONC, nikoli JSON
{
 // Poznámka pro autora
 "jmeno":"Eva"
}

Odstraň komentář nebo zvol rozšířený formát jen tehdy, když jej příjemce výslovně podporuje. Pokud parser selže na prvním znaku, zkontroluj také skutečné bajty: UTF-8 BOM je EF BB BF. RFC 8259 zakazuje jeho přidání do přenášeného JSON, parser jej však může tolerovat. Ulož vlastní soubor jako UTF-8 bez BOM; porovnání chování parserů a opravu v Pythonu najdeš v kapitole kódování JSON. Neodstraňuj libovolné znaky uvnitř dat.