Syntaxe JSON: hodnoty, objekty a pole

JSON má jen několik pravidel zápisu, ale parser je vyžaduje do posledního znaku. Kapitola projde hodnoty, objekty a pole, bílé znaky, duplicitní klíče a kódování a ukáže chyby, na kterých parsery nejčastěji končí.

Autor: Aktualizováno

JSON text je jedna hodnota

Celý JSON dokument, ve specifikaci JSON text, je jedna hodnota, před kterou a za kterou smí být bílé znaky. Nejčastěji je to objekt nebo pole, ale platný JSON text je i samotný řetězec "text" nebo číslo 42. Starší RFC 4627 povolovalo jen objekt nebo pole; pro API je proto bezpečnější posílat na nejvyšší úrovni objekt, s ním si poradí i staré knihovny.

HodnotaZápis
objekt{ "název": hodnota, … }
pole[ hodnota, hodnota, … ]
řetězec"text" (jen dvojité uvozovky)
číslo-12, 3.14, 1e3
logická hodnotatrue, false
prázdná hodnotanull

Objekty a pole

Objekt je ve složených závorkách a obsahuje dvojice název: hodnota oddělené čárkou. Název je vždy řetězec ve dvojitých uvozovkách. Objekt je podle specifikace neuspořádaný: na pořadí dvojic by program neměl záviset, i když ho většina knihoven zachová.

Pole je v hranatých závorkách a obsahuje hodnoty oddělené čárkou. Pořadí v poli je součástí dat. Hodnoty v jednom poli mohou být různého typu, i když v praxi se kvůli zpracování drží jeden typ. Objekty a pole se libovolně vnořují a mohou být prázdné:

faktura.json
{
  "faktura": {
    "cislo": "FV2026-042",
    "polozky": [
      { "kod": "HR-01", "pocet": 2 },
      { "kod": "PO-02", "pocet": 1 }
    ],
    "poznamky": []
  }
}

Bílé znaky

Mezi hodnotami a kolem znaků { } [ ] : , smí být libovolně mnoho mezer, tabulátorů a konců řádků (LF i CR). Jiné bílé znaky, třeba nezlomitelná mezera, povolené nejsou. Odsazení tedy na význam nemá vliv a {"a":1} je totéž co stejný objekt rozepsaný na víc řádků. Uvnitř řetězců to neplatí, tam se tabulátor a konec řádku musí zapsat jako \t a \n (viz Řetězce).

Co je a co není platný JSON

JSON vznikl podle JavaScriptu, ale je mnohem přísnější. Všechny ukázky v tabulce jsou ověřené parserem:

ZápisPlatný JSON?PročNástroj
{"a": 1}anoobjekt s jednou dvojicíVyzkoušet
[1, "dva", true, null]anopole může míchat typyVyzkoušet
"text"anoJSON text může být i samotná hodnota (RFC 8259)Vyzkoušet
42anosamotné čísloVyzkoušet
{'a': 1}neřetězce a klíče jen ve dvojitých uvozovkáchVyzkoušet
{a: 1}neklíč musí být řetězec v uvozovkáchVyzkoušet
[1, 2,]nečárka za posledním prvkem není povolenáVyzkoušet
{"a": 1} // poznámkaneJSON nezná komentářeVyzkoušet
{"a": undefined}neundefined není hodnota JSONVyzkoušet
{"a": True}neliterály jsou jen malými písmeny: true, false, nullVyzkoušet

Typický ručně psaný soubor a jeho opravená verze:

Chybně
{
  'cislo': 'FV2026-042',
  polozky: [1, 2, 3,],
  uhrazeno: True,   // zaplaceno převodem
}
Správně
{
  "cislo": "FV2026-042",
  "polozky": [1, 2, 3],
  "uhrazeno": true,
  "poznamka": "zaplaceno převodem"
}

Pokud potřebuješ komentáře nebo čárky navíc, nejde o JSON, ale o rozšíření jako JSONC nebo JSON5. Standardní parser takový soubor odmítne.

Duplicitní klíče

Gramatika JSON duplicitní názvy v jednom objektu nezakazuje, RFC 8259 jen doporučuje (SHOULD), aby byly jedinečné. Chování parserů pak specifikace označuje za nepředvídatelné: některé vrátí poslední hodnotu, jiné první, ohlásí chybu nebo vrátí obě. Změřené chování (Node.js 25, Python 3.14 a PHP 8.4):

VstupJavaScriptPythonPHP
{"a":1,"a":2}{"a":2}{'a': 2}['a' => 2]

Všechny tři vrátí poslední hodnotu, na jiné knihovně to ale záviset nemusí. Problém nastane, když stejný dokument čtou dva různé parsery, třeba kontrola na bráně a aplikace za ní: každý může vidět jinou hodnotu. Přísnější profil I-JSON (RFC 7493) duplicitní názvy zakazuje (MUST NOT). Generuj JSON knihovnou a duplicitní klíče nikdy nepoužívej.

Kódování a BOM

JSON vyměňovaný mezi systémy musí být v UTF-8 (RFC 8259, § 8.1). Starší specifikace připouštěly i UTF-16 a UTF-32, v praxi se ale ujalo jen UTF-8. Značka BOM se na začátek JSON textu přenášeného po síti přidávat nesmí; parser ji smí ignorovat, ale nemusí. Testované parsery ji neignorují a skončí chybou:

VstupJavaScriptPythonPHP
[BOM]{"a":1}chybachybachyba

Soubor s BOM, typicky uložený v editoru na Windows, ulož znovu jako „UTF-8 bez BOM“, nebo BOM před parsováním odstraň (v Pythonu kódováním utf-8-sig).

Rozšíření a limity parserů

Specifikace parseru dovoluje přijímat i zápisy mimo JSON. Proto Python ve výchozím nastavení přijme NaN nebo Infinity, které platný JSON nejsou. Parser si také smí nastavit limity: maximální velikost textu, hloubku vnoření, rozsah čísel a délku řetězců. U dat z cizích zdrojů je rozumné limity nastavit vědomě, například hloubku vnoření v PHP třetím parametrem json_decode().

Doporučené postupy

  • JSON vytvářej knihovnou (JSON.stringify, json.dumps, json_encode), ne skládáním řetězců.
  • Klíče v objektu drž jedinečné a nespoléhej na jejich pořadí.
  • Ukládej a posílej v UTF-8 bez BOM, s MIME typem application/json.
  • U API dávej na nejvyšší úroveň objekt; přidat do něj později další pole nic nerozbije.
  • Hotový dokument zkontroluj ve validátoru, strukturu dat pak hlídá JSON Schema.