Přejít k navigační liště

Zdroják » JavaScript » Načítáme a zpracováváme JSON

Načítáme a zpracováváme JSON

JSON (JavaScript Object Notation) používají webové aplikace k výměně dat. V minulém dílu jsme si JSON představili a ukázali jsme si, jak se pomocí něj zapisují data. Dnes si ukážeme, jak formát JSON pomocí AJAXu načíst a upozorníme na některé problémy s tím spojené.

Nyní, když víme, co je to JSON a k čemu slouží, můžeme se podívat, jak se s JSON pracuje.

JSON a AJAX

JSON budeme nejčastěji používat ve spojení s AJAXem. Skočme do toho po hlavě a ukažme si první příklad.

Máme webovou aplikaci Budulínek, která monitoruje počet lišek, jenž dosud zůstaly v noře (podobnost s dějem pohádky není náhodná). Aplikace se periodicky pomocí AJAXu dotazuje serveru na aktuální stav. Server zasílá odpověď ve formátu JSON, kterou aplikace zobrazí uživateli. Proces nám obstará tento kód:

$.get("nora.php", function(jsondata) {

  var stav_lisek_v_nore = eval("(" + jsondata + ")");

  // zpracování stav_lisek_v_nore a zobrazení výsledků uživateli
  // ...

}); 

V příkladu jsme použili javascriptový framework jQuery. Metoda $.get(url, callback) pošle AJAXem asynchronní požadavek na adresu v prvním argumentu. Jakmile je požadavek dokončen, je zavolána callback funkce, která ve svém argumentu obdrží odpověď serveru.

Poznámka: Místo jQuery můžete stejně dobře použít nativní AJAX nebo jakýkoliv jiný javascriptový framework. My se budeme u výkladu držet jQuery, protože nám umožní soustředit se nikoliv na zápis AJAXu, ale na vykládanou problematiku.

Jádrem našeho kódu je konstrukce:

eval("(" + jsondata + ")"); 

Ta zajistí převedení odpovědi serveru uložené v řetězci „jsondata“ ve formátu JSON na analogickou datovou strukturu v JavaScriptu. S tou pak pracujeme stejně jako s jakoukoliv jinou datovou strukturou.

Přidání kulatých závorek okolo proměnné jsondata je nutné. Spuštění metody eval bez přidání závorek nepovede v některých případech ke správnému výsledku. Kupříkladu volání eval('{ "x": 127, "y": 11 }') skončí syntaktickou chybou. Název vlastnosti „x“ vloženého objektu je totiž interpretována jako návěští. Návěští ovšem nesmí obsahovat uvozovky a interpret zde selže. Po přidání závorek výraz eval('({ "x": 127, "y": 11 })') proběhne v pořádku.

Specifikace ECMAScriptu přímo říká, že výraz nesmí začínat složenou závorkou, jelikož by mohla být považována za začátek bloku. Což je přesně to, k čemu v daném případě došlo. Proto se doporučuje řetězec s JSON vždy obalit kulatými závorkami a problém vás nemusí trápit.

Zkrácená verze

Uvedený proces lze dnes považovat za rutinu. Frameworky proto nabízí funkci, která obstará jak načtení JSON, tak jeho převedení na javascriptový objekt. Pokud použijeme jQuery, vypadá zkrácený kód takto:

$.getJSON("nora.php", function(stav_lisek_v_nore) {

  // zpracování stav_lisek_v_nore a zobrazení výsledků uživateli
  // ...

}); 

Metoda $.getJSON(url, callback) funguje obdobně jako dříve představená metoda $.get() s tím rozdílem, že sama provede zavolání eval().

Nebezpečí skryté v eval

Načítání JSON pomocí eval je jedním z nejčastějších způsobů (interně jej používá jQuery a možná i některé další frameworky), ale z bezpečnostního hlediska s ním nelze souhlasit. Pokud by odpověď serveru obsahovala podstrčený javascriptový kód jako v následujícím případě, bude tento kód na straně webového prohlížeče vykonán!

[1, 45, alert('** You are Doomed! **')] 

Uvedený zápis sice není platný formát JSON, my ovšem jeho platnost nikde neověřujeme! Jak nebezpečí předejít? Existují dvě cesty. Buď se pokusíme podstrčený kód detekovat a teprve při negativním výsledku zpracovat data metodou eval, nebo se můžeme volání metody eval zcela vyhnout a ke zpracování dat použít JSON parser.

Detekce podstrčeného kódu

Podstrčený kód můžeme snadno odhalit regulárním výrazem:

var my_JSON_object = !(/[^,:{}[]0-9.-+Eaeflnr-u nrt]/.test(
     text.replace(/"(\.|[^"\])*"/g, ''))) && eval('(' + text + ')'); 

Příklad byl převzat z RFC 4627 a dokáže odhalit jakýkoliv podstrčený kód. Napřed odstraní veškeré řetězce (uvnitř uvozovek může být prakticky cokoliv a nevadí to) a zkontroluje znaky, které zbyly.

Parser JSON

Douglas Crockford (tvůrce JSON) vytvořil parser JSON a uvolnil jej jako public domain. Parser nejen zajistí, že data neobsahují podstrčený kód, ale zároveň ověří, že se jedná o platný formát JSON (v předchozím případě jsme platný JSON jen optimisticky předpokládali). V případě problému vyvolá výjimku. Použití je jednoduché:

var myObject = json_parse(jsondata); 

Nenechme se ale ukolébat spolehlivostí parseru. Nezapomeňme, že ačkoliv při použití parseru si můžeme být zcela jisti, že načtená struktura je validní JSON, parser nám sám o sobě nezaručí, že načtená data jsou v námi očekávané datové struktuře (očekáváme pole s řetězci nebo objekt s čísly?). To si musíme zkontrolovat sami (v příkladech v článku jsme správnost dat opět optimisticky předpokládali). Existuje návrh pro JSON Schema (analogie k XML Schema), které by tuto kontrolu usnadnilo.

Je kontrola nutná?

Existuje několik důvodů, proč data kontrolovat a vy sami musíte zvážit, zda platí i pro vás.

Tím prvním je, že jste paranoidní a nevěříte ani datům z vlastního serveru. Přesto ošetřit JSON před nechtěným vložením kódu by neměl být problém. Správné escapování zpětných lomítek a uvozovek u textových vstupů postačí.

Vážnějším důvodem je, pokud přebíráte data z jiných zdrojů. Pak nemáte nad daty kontrolu. Pokud by ona vzdálená webová aplikace byla napadena, může být jejím prostřednictvím napadena i aplikace vaše.

Zatím takový útok nepamatujeme, ale pokud jednoho dne bude napaden Twitter, Delicious nebo jiná služba, jejíž rozhraní je široce používané, možná budeme nemile překvapeni. Ideální pro spojení s kódem zneužívajícím díru webového prohlížeče. Ještě stále datům v JSON věříte?

JSON na jiných doménách

Pokud potřebujeme načíst JSON z jiných domén, nemůžeme AJAX použít, ten totiž dotazování mezi doménami neumožňuje. Můžeme si ovšem pomoci jednoduchým skriptem na našem serveru, který poslouží jako proxy, a přenos dat z jiné domény nám zprostředkuje.

Jiný způsob používá služba Delicious, jejíž rozhraní kromě běžných JSON generuje speciální skripty, které obsahují načtený JSON (ukázka). Zatímco volání AJAXu je omezené na stejnou doménu, tak vkládání skriptů pomocí značky skript již takto omezené není. Podobný přístup volí i Yahoo. Problémem je v takovém případě bezpečnost (spouštíme kód načítaný z cizího serveru).

Ačkoliv na Webu najdeme řadu služeb s veřejným API často podporujících JSON, bez použití jednoho z výše uvedených triků je nedokážeme z naší webové aplikace zavolat. Mohli bychom říci, že prostředí dnešního Webu je takovému používání přes všechnu popularitu relativně nepřátelské. Jak si ještě ukážeme, to se časem snad změní.

Význam JSON roste

Předvedli jsme si použití JSON v komunikaci s vlastní aplikací pomocí AJAXu a zmínili jsme možnosti v komunikaci s aplikacemi třetích stran.

To ale není vše. Význam JSON v budoucnu vzroste, protože:

  • Do prohlížečů se časem dostane nová verze AJAXu, která není omezená na stejnou doménu (existuje přísný mechanismus určující, který požadavek povolit a který nikoliv).
  • Prohlížeče časem začnou podporovat mechanismus HTML5 pro komunikaci oken (rámců) z různých domén mezi sebou.

Ať již v budoucnu budeme s cizí webovou aplikací komunikovat přímo pomocí AJAXu nebo ji načteme do iframe a budeme posílat zprávy skrze něj, JSON bude v obou případech jeden z hlavních formátů pro výměnu dat a vzhledem ke své jednoduchosti se možná stane i formátem prakticky jediným.

Pokračování příště

S rostoucím významem JSON je nutné zjednodušit i práci s ním a jednou pro vždy zrušit jeho načítání metodou eval. Proto se do webových prohlížečů zavádí nativní rozhraní pro práci s JSON. Ale o tom až v dalším díle.

Příklad k vyzkoušení

Příklady z článku si můžete vyzkoušet online v ukázkové aplikaci.

Odkazy

Používáte ke zpracování JSON eval?

Komentáře

Subscribe
Upozornit na
guest
7 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
gofry

Myslím, že dáta z vlastného servera je zbytočné kontrolovať. Ak už raz bude napadnutý server, nič nebráni tomu aby útočník zmenil aj samotný javascript.

Sten

Není to zbytečné kontrolovat. Pokud ten JSON neběží přes HTTPS, nikdy si nemůžete být jisti, odkud ta data vlastně přijdou.

Anonymní

No tak nevim – věci, u kterejch mi záleží na bezpečnosti asi na HTTP dělat nebudu, u věcí kterejch nezáleží je to jedno. Když mam dobře ošetřenej server, tak případnej pád klienta
nevadí, ne?

František Kučera

To je sice pravda, ale v takovém případě může útočník podvrhnout tu HTML stránku nebo jiný skript — nemusí útočit jen na ten JSON.

Kontrola má smysl spíš kvůli chybám softwaru — když programátor udělá chybu a ze serveru přijde neplatná odpověď, tak klient zobrazí nějakou učesanou omluvu, místo aby se program choval nepředvídatelně (např. rozsypaný výstup/formáto­vání).

uziv

:-)

Mazarik

videli ste uz prehliadac, ktory dokaze spracovavat SOAP? Ja viem iba o Firefoxe do verzie 2 a to iba v rezime rozsireni. Ostatne prehliadace by som tipoval, ze to vedia pridanim nejakeho doplnku. Samozrejme ako klienti neexistuju len webove prehliadace.

wen

Protoze SOAP je vlastne XML.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.