Úvod do JsonPath

1. Prehľad

Jednou z výhod XML je dostupnosť spracovania - vrátane XPath - ktoré je definované ako štandard W3C. Pre JSON sa objavil podobný nástroj s názvom JSONPath.

Tento článok bude obsahovať úvod do Jayway JsonPath, implementácia Java špecifikácie JSONPath. Opisuje nastavenie, syntax, bežné API a ukážku prípadov použitia.

2. Inštalácia

Ak chcete použiť JsonPath, jednoducho musíme do Maven pom zahrnúť závislosť:

 com.jayway.jsonpath json-path 2.4.0 

3. Syntax

V tejto časti sa na demonštráciu syntaxe a rozhraní API JsonPath použije nasledujúca štruktúra JSON:

{"tool": {"jsonpath": {"creator": {"name": "Jayway Inc.", "location": ["Malmo", "San Francisco", "Helsingborg"]}}}, "kniha ": [{" title ":" Beginning JSON "," price ": 49.99}, {" title ":" JSON at Work "," price ": 29.99}]}

3.1. Zápis

JsonPath používa špeciálnu notáciu na reprezentáciu uzlov a ich pripojení k susedným uzlom na ceste JsonPath. Existujú dva štýly zápisu, a to bodka a hranatá zátvorka.

Obe nasledujúce cesty odkazujú na ten istý uzol z vyššie uvedeného dokumentu JSON, ktorý je tretím prvkom v rámci umiestnenie oblasť tvorca uzol, ktorý je potomkom jsonpath predmet patriaci k nástroj pod koreňovým uzlom.

S bodkovou notáciou:

$ .tool.jsonpath.creator.location [2]

So zátvorkou:

$ ['nástroj'] ['jsonpath'] ['tvorca'] ['umiestnenie'] [2]

Znak dolára ($) predstavuje objekt člena root.

3.2. Operátorov

V JsonPath máme niekoľko užitočných operátorov:

Koreňový uzol ($): Tento symbol označuje koreňového člena štruktúry JSON bez ohľadu na to, či ide o objekt alebo pole. Príklady jeho použitia boli zahrnuté v predchádzajúcej podkapitole.

Aktuálny uzol (@): Predstavuje uzol, ktorý sa spracováva, väčšinou používaný ako súčasť vstupných výrazov pre predikáty. Predpokladajme, že máme do činenia s kniha pole vo vyššie uvedenom dokumente JSON, výraz kniha [? (@. price == 49,99)] odkazuje na prvý kniha v tom poli.

Divoká karta (*): Vyjadruje všetky prvky v uvedenom rozsahu. Napríklad kniha [*] označuje všetky uzly vo vnútri a kniha pole.

3.3. Funkcie a filtre

JsonPath má tiež funkcie, ktoré je možné použiť na koniec cesty na syntézu výstupných výrazov tejto cesty: min (), max (), priem. (), stddev (), dĺžka ().

Nakoniec - máme filtre; toto sú boolovské výrazy na obmedzenie vrátených zoznamov uzlov iba na tie, ktoré volajúce metódy potrebujú.

Niekoľko príkladov je rovnosť (==), zhoda s regulárnym výrazom (=~), začlenenie (v), skontrolujte prázdnotu (prázdny). Filtre sa používajú hlavne pre predikáty.

Celý zoznam a podrobné vysvetlenie rôznych operátorov, funkcií a filtrov nájdete v projekte JsonPath GitHub.

4. Prevádzka

Predtým, ako sa pustíme do operácií, stručná poznámka - táto časť využíva ukážkovú štruktúru JSON, ktorú sme definovali skôr.

4.1. Prístup k dokumentom

JsonPath má pohodlný spôsob prístupu k dokumentom JSON, ktorý je statický čítať API:

 T JsonPath.read (reťazec jsonString, reťazec jsonPath, predikát ... filtre);

The čítať API môžu pracovať so staticky plynulými API, aby poskytli väčšiu flexibilitu:

 T JsonPath.parse (String jsonString) .read (String jsonPath, Predicate ... filtre);

Ostatné preťažené varianty čítať možno použiť pre rôzne typy zdrojov JSON, vrátane Objekt, InputStream, URLa Súbor.

Pre zjednodušenie test tejto časti neobsahuje predikáty v zozname parametrov (prázdny varargs); predikáty sa bude diskutovať v ďalších pododdieloch.

Začnime definovaním dvoch vzorových ciest, na ktorých treba pracovať:

Reťazec jsonpathCreatorNamePath = "$ ['nástroj'] ['jsonpath'] ['tvorca'] ['meno']"; Reťazec jsonpathCreatorLocationPath = "$ ['nástroj'] ['jsonpath'] ['tvorca'] ['umiestnenie'] [*]";

Ďalej vytvoríme a DocumentContext objekt analýzou daného zdroja JSON jsonDataSourceString. Novo vytvorený objekt sa potom použije na čítanie obsahu pomocou vyššie definovaných ciest:

DocumentContext jsonContext = JsonPath.parse (jsonDataSourceString); Reťazec jsonpathCreatorName = jsonContext.read (jsonpathCreatorNamePath); Zoznam jsonpathCreatorLocation = jsonContext.read (jsonpathCreatorLocationPath);

Prvý čítať API vráti a String obsahuje meno tvorcu JsonPath, zatiaľ čo druhý vracia zoznam jeho adries. A použijeme JUnit Tvrdiť API na potvrdenie, že metódy fungujú podľa očakávania:

assertEquals ("Jayway Inc.", jsonpathCreatorName); assertThat (jsonpathCreatorLocation.toString (), containsString ("Malmo")); assertThat (jsonpathCreatorLocation.toString (), containsString ("San Francisco")); assertThat (jsonpathCreatorLocation.toString (), containsString ("Helsingborg"));

4.2. Predikáty

Teraz, keď sme skončili so základmi, definujme nový príklad JSON, na ktorom budeme pracovať, a ilustrujme vytvorenie a použitie predikátov:

{"book": [{"title": "Beginning JSON", "author": "Ben Smith", "price": 49.99}, {"title": "JSON at Work", "autor": "Tom Marrs "," price ": 29.99}, {" title ":" Naučte sa JSON za DEŇ "," autor ":" Acodemy "," price ": 8.99}, {" title ":" JSON: Otázky a odpovede ", "autor": "George Duckett", "cena": 6.00}], "cenové rozpätie": {"lacné": 10.00, "stredné": 20.00}}

Predikáty určujú pravdivé alebo nepravdivé vstupné hodnoty pre filtre na zúženie vrátených zoznamov iba na zhodné objekty alebo polia. A Predikát môžu byť ľahko integrované do a Filtrovať použitím ako argument pre svoju statickú továrenskú metódu. Pomocou toho je potom možné načítať požadovaný obsah z reťazca JSON Filtrovať:

Filter expensiveFilter = Filter.filter (Criteria.where ("price"). Gt (20,00)); Zoznam drahý = JsonPath.parse (jsonDataSourceString) .read ("$ ['book'] [?]", drahýFilter); predicateUsageAssertionHelper (drahé);

Môžeme tiež definovať naše prispôsobené Predikát a použiť to ako argument pre čítať API:

Predicate expensivePredicate = new Predicate () {public boolean apply (PredicateContext context) {String value = context.item (Map.class) .get ("price"). ToString (); návrat Float.valueOf (hodnota)> 20,00; }}; Zoznam drahý = JsonPath.parse (jsonDataSourceString) .read ("$ ['kniha'] [?]", drahýPredicate); predicateUsageAssertionHelper (drahé);

Nakoniec sa dá priamo použiť predikát čítať API bez vytvárania akýchkoľvek objektov, ktoré sa nazýva inline predikát:

Zoznam drahý = JsonPath.parse (jsonDataSourceString) .read ("$ ['kniha'] [? (@ ['cena']> $ ['cenový rozsah'] ['stredný'])]"); predicateUsageAssertionHelper (drahé);

Všetci traja z Predikát príklady vyššie sú overené pomocou nasledujúcej metódy pomocného tvrdenia:

private void predicateUsageAssertionHelper (List predicate) {assertThat (predicate.toString (), containsString ("Beginning JSON")); assertThat (predicate.toString (), containsString ("JSON at Work")); assertThat (predicate.toString (), nie (containsString ("Naučte sa JSON za DEŇ"))); assertThat (predicate.toString (), nie (containsString ("JSON: Otázky a odpovede"))); }

5. Konfigurácia

5.1. možnosti

Jayway JsonPath poskytuje niekoľko možností na vyladenie predvolenej konfigurácie:

  • Možnosť.AS_PATH_LIST: Vráti cesty hodnotiacich zásahov namiesto ich hodnôt.
  • Možnosť. DEFAULT_PATH_LEAF_TO_NULL: Vráti hodnotu null pre chýbajúce listy.
  • Možnosť. ALWAYS_RETURN_LIST: Vráti zoznam, aj keď je cesta jednoznačná.
  • Možnosť.SUPPRESS_EXCEPTIONS: Zaisťuje, aby sa z vyhodnotenia cesty nešírili žiadne výnimky.
  • Možnosť. REQUIRE_PROPERTIES: Vyžaduje vlastnosti definované v ceste, keď sa vyhodnocuje neurčitá cesta.

Tu je postup Možnosť nanáša sa od nuly:

Configuration configuration = Configuration.builder (). Options (Option.). Build ();

a ako ho pridať do existujúcej konfigurácie:

Konfigurácia newConfiguration = configuration.addOptions (voliteľné.);

5.2. SPI

Predvolená konfigurácia JsonPath pomocou Možnosť by malo stačiť na väčšinu úloh. Používatelia so zložitejšími prípadmi použitia však môžu upraviť správanie servera JsonPath podľa svojich špecifických požiadaviek - pomocou troch rôznych SPI:

  • JsonProvider SPI: Umožňuje nám zmeniť spôsoby, ako JsonPath analyzuje a spracováva dokumenty JSON
  • Poskytovateľ mapovania SPI: Umožňuje prispôsobenie väzieb medzi hodnotami uzlov a vrátenými typmi objektov
  • CacheProvider SPI: Upravuje spôsoby ukladania ciest do vyrovnávacej pamäte, čo môže pomôcť zvýšiť výkon

6. Príklad prípadov použitia

Teraz, keď dobre rozumieme funkčnosti, na ktorú je možné použiť JsonPath, sa pozrime na príklad.

Táto časť ilustruje prácu s údajmi JSON vrátenými z webovej služby - predpokladajme, že máme filmovú informačnú službu, ktorá vracia nasledujúcu štruktúru:

[{"id": 1, "title": "Casino Royale", "director": "Martin Campbell", "v hlavnej úlohe": ["Daniel Craig", "Eva Green"], "desc": "Dvadsiaty prvý Film Jamesa Bonda "," dátum vydania ": 1163466000000," pokladňa ": 594275385}, {" id ": 2," title ":" Quantum of Solace "," režisér ":" Marc Forster "," v hlavnej úlohe ": ["Daniel Craig", "Olga Kurylenko"], "desc": "Dvadsiaty druhý film Jamesa Bonda", "dátum vydania": 1225242000000, "pokladňa": 591692078}, {"id": 3, "názov" : "Skyfall", "režisér": ​​"Sam Mendes", "v hlavnej úlohe": ["Daniel Craig", "Naomie Harris"], "desc": "Dvadsiaty tretí film Jamesa Bonda", "dátum uvedenia": 1350954000000, "box office": 1110526981}, {"id": 4, "title": "Spectre", "director": "Sam Mendes", "v hlavnej úlohe": ["Daniel Craig", "Lea Seydoux"], "desc. ":" Dvadsiaty štvrtý film Jamesa Bonda "," dátum vydania ": 1445821200000," pokladňa ": 879376275}]

Kde je hodnota dátum vydania pole je doba trvania od Epochy v milisekundách a pokladňa je výnos filmu v kine v amerických dolároch.

Budeme spracovávať päť rôznych pracovných scenárov súvisiacich s požiadavkami GET, za predpokladu, že vyššie uvedená hierarchia JSON bola extrahovaná a uložená v String premenná s názvom jsonString.

6.1. Získavanie údajov o objektoch vzhľadom na ID

V tomto prípade použitia klient požaduje podrobné informácie o konkrétnom filme poskytnutím presných údajov serveru id toho. Tento príklad ukazuje, ako server vyhľadáva požadované údaje pred návratom ku klientovi.

Povedzme, že musíme nájsť záznam s id rovné 2. Nižšie je uvedené, ako je proces implementovaný a testovaný.

Prvým krokom je vyzdvihnutie správneho dátového objektu:

Objekt dataObject = JsonPath.parse (jsonString) .read ("$ [? (@. Id == 2)]"); Reťazec dataString = dataObject.toString ();

JUnit Tvrdiť API potvrdzuje existenciu niekoľkých polí:

assertThat (dataString, containsString ("2")); assertThat (dataString, containsString ("Quantum of Solace")); assertThat (dataString, containsString („Dvadsaťsekundový film Jamesa Bonda“));

6.2. Získanie názvu filmu v hlavnej úlohe

Povedzme, že sa chceme poobzerať po filme, v ktorom si hlavnú úlohu zahrala herečka Eva Green. Server sa musí vrátiť titul filmu, ktorý Eva Green je súčasťou hrať pole.

Nasledujúci test ilustruje, ako to urobiť, a overí vrátený výsledok:

@Test public void givenStarring_whenRequestingMovieTitle_thenSucceed () {Zoznam dataList = JsonPath.parse (jsonString) .read ("$ [? ('Eva Green' in @ ['starring'])]"); Názov reťazca = (Reťazec) dataList.get (0) .get ("title"); assertEquals ("Casino Royale", názov); }

6.3. Výpočet celkových výnosov

Tento scenár využíva funkciu JsonPath s názvom dĺžka () zistiť počet filmových záznamov a vypočítať celkový príjem všetkých filmov. Implementácia a testovanie sa demonštrujú takto:

@Test public void givenCompleteStructure_whenCalculatingTotalRevenue_thenSucceed () {DocumentContext context = JsonPath.parse (jsonString); int dĺžka = kontext.číslo ("$. dĺžka ()"); dlhý výnos = 0; for (int i = 0; i <length; i ++) {income + = context.read ("$ [" + i + "] ['pokladňa']", Long.class); } assertEquals (594275385L + 591692078L + 1110526981L + 879376275L, výnosy); }

6.4. Film s najvyššími príjmami

Tento prípad použitia ilustruje použitie inej ako predvolenej možnosti konfigurácie JsonPath Možnosť.AS_PATH_LIST, aby ste našli film s najvyššími príjmami. Jednotlivé kroky sú opísané nižšie.

Spočiatku musíme extrahovať zoznam všetkých výnosov z pokladne filmov a potom ho previesť na pole na zoradenie:

DocumentContext context = JsonPath.parse (jsonString); Zoznam tržieb = context.read ("$ [*] ['pokladňa']"); Celé číslo [] incomeArray = tržbyList.toArray (nové celé číslo [0]); Arrays.sort (výnosové pole);

The najvyšší príjem premenná sa dá ľahko zistiť z výnosové pole zoradené pole, ktoré sa potom použije na vypracovanie cesty k záznamu filmu s najvyššími príjmami:

int najvyššiaRežim = tržbaArray [tržbaArray.length - 1]; Konfigurácia pathConfiguration = Configuration.builder (). Options (Option.AS_PATH_LIST) .build (); Zoznam pathList = JsonPath.using (pathConfiguration) .parse (jsonString) .read ("$ [? (@ ['Box office'] ==" + nejvyššívýnos + ")]");

Na základe tejto vypočítanej cesty titul príslušného filmu je možné určiť a vrátiť:

Mapa dataRecord = context.read (pathList.get (0)); Názov reťazca = dataRecord.get ("názov");

Celý proces overuje Tvrdiť API:

assertEquals ("Skyfall", názov);

6.5. Najnovší film režiséra

Tento príklad ilustruje spôsob, ako zistiť trvajúci film režírovaný režisérom Sam Mendes.

Na začiatok zoznam všetkých filmov, ktoré režíroval Sam Mendes je vytvorené:

DocumentContext context = JsonPath.parse (jsonString); Zoznam dataList = context.read ("$ [? (@. director == 'Sam Mendes')]");

Tento zoznam sa používa na extrakciu dátumov vydania. Tieto dátumy sa uložia do poľa a potom sa zoradia:

Zoznam dateList = nový ArrayList (); for (Map item: dataList) {Object date = item.get ("date release"); dateList.add (dátum); } Long [] dateArray = dateList.toArray (nový Long [0]); Arrays.sort (dateArray);

The lastestTime premenná, ktorá je posledným prvkom zoradeného poľa, sa používa v kombinácii s riaditeľ hodnota poľa na určenie titul požadovaného filmu:

long latestTime = dateArray [dateArray.length - 1]; Zoznam finalDataList = context.read ("$ [? (@ ['director'] == 'Sam Mendes' && @ ['dátum vydania'] ==" + latestTime + ")]"); Názov reťazca = (Reťazec) finalDataList.get (0) .get ("title");

Nasledujúce tvrdenie dokázalo, že všetko funguje podľa očakávaní:

assertEquals ("Strašidlo", názov);

7. Záver

Tento tutoriál obsahuje základné vlastnosti Jayway JsonPath - mocného nástroja na prechádzanie a analýzu dokumentov JSON.

Aj keď má JsonPath niektoré nevýhody, ako napríklad nedostatok operátorov na dosiahnutie rodičovských alebo súrodeneckých uzlov, môže byť veľmi užitočný v mnohých scenároch.

Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v a Projekt GitHub.


$config[zx-auto] not found$config[zx-overlay] not found