Feltételezzük, hogy ismered a JSON szintaxisát és adattípusait.
A jq úgy működik, hogy a beérkező JSON adatot egy kifejezésen (amely szűrők csővezetékeként íródik le) vezeti át, hogy elérje a kívánt átalakított adatot.
A jq nyelvet a jq program valósítja meg.
Ez a program több hasznos parancssori kapcsolót kínál, amelyekkel szabályozhatod, hogyan fogyasztja a bemenetet és hogyan jeleníti meg a kimenetet.
Az alábbi példákban ezekkel találkozol majd:
-n vagy --null-input
A jq program általában egy fájlt kap, amit beolvas, vagy adatot küldesz a bemenetére.
A --null-input kapcsolóval bemenet nélkül is generálhatsz JSON adatot.
-c vagy --compact-output
A jq alapértelmezés szerint szépen formázva írja ki a kimenetét.
Rendkívül hasznos az emberek számára, ha az adat szépen formázva jelenik meg.
A gépeknek azonban erre nincs szükségük: a --compact-output kapcsoló eltávolítja a formázó whitespace-t, hogy a keletkező JSON mérete a lehető legkisebb legyen.
-f filename vagy --from-file filename
A jq programot a filename nevű fájlból olvassa be ahelyett, hogy a parancssorban adnád meg.
A sed és az awk is ugyanerre a célra használja a -f kapcsolót.
Ezzel a gyakorlófeladatok tesztszkriptjeiben találkozol majd.
A lecke további része a jq nyelvére összpontosít.
A szűrőket kifejezéseknek is nevezik.
Egy szűrő bemenetet vesz és kimenetet állít elő.
Ahogy a unix shellben dolgozol, a szűrőket itt is összefűzheted egy | csővezetékkel, hogy az egyik szűrő kimenetét a másik bemenetéhez kapcsold.
.
Ez a legegyszerűbb szűrő. Egyszerűen átadja a bemenetét a kimenetének.
$ echo '[1, 2, 3]' | jq '.'
[
1,
2,
3
]
Ez egy gyors bevezetés a tömbökkel való munkába. Ezt a témát később részletesebben is tárgyaljuk.
A tömb elemeihez szögletes zárójellel férsz hozzá, és az indexelés nullától indul.
$ echo '[10, 20, 30]' | jq '.[1]'
20
Egy szűrő úgy építhet tömböt, hogy egy kifejezést [ és ] közé zár
ismert elemlistával:
jq -n '[1, 2, 3]'
elemfolyam összegyűjtéséhez: például
a range egy függvény, amely számok folyamát adja ki
$ jq -n 'range(10; 70; 15)'
10
25
40
55
A [] használatával a kifejezés eredményei egy tömbbe gyűlnek
$ jq -c -n '[range(10; 70; 15)]'
[10,25,40,55]
A vessző nem csupán olyan szintaxis, amely elválasztja a tömb elemeit. A vessző egy operátor, amely folyamokat fűz össze.
Például a [1, 2, 3] egy szűrő, amely a [] tömbkonstruktort használja, hogy összegyűjtse a 1, 2 és 3 kifejezés összefűzésének eredményét.
Észrevetted a pontosvesszőket a fenti range(10; 70; 15) kifejezésben?
Mivel a vesszőknek meghatározott szerepük van a jq nyelvben, a több argumentumot fogadó függvények pontosvesszővel választják el az argumentumokat.
Gyors bevezetés az objektumokba.
A sok programozási nyelvhez hasonlóan ponttal férsz hozzá az objektum tulajdonságaihoz
$ echo '{"foo": {"bar": "qux"}}' | jq '.foo.bar'
"qux"
Szögletes zárójeleket az objektumoknál is használhatsz, de akkor az idézőjelek kötelezők a string literálokhoz. Ez az egyik módja annak, hogy szóközt tartalmazó kulcsokkal dolgozz.
$ echo '{"foo bar": "qux"}' | jq '.["foo bar"]'
"qux"
Egy objektumot {} és key: value párokkal hozhatsz létre.
Az olyan kulcsok körül, amelyek „egyszerű” stringek, nem kötelezők az idézőjelek.
jq -n '{question: (6 * 9), answer: 42}'
az alábbi kimenetet adja
{
"question": 54,
"answer": 42
}
Ahhoz, hogy a kulcsot kifejezésként kezeld, zárójelbe kell tenned (a következő is ugyanazt adja eredményül, mint a fenti).
echo '[{"key":"question", "value":54}, {"key":"answer", "value":42}]' \
| jq '{(.[0].key): .[0].value, (.[1].key): .[1].value}'
Például ha a file.json a következőt tartalmazza
{
"key1": "value1",
"key2": [5, 15, 25]
}
Számítsuk ki a key2 tömb hosszát:
$ jq '.key2 | length' file.json
3
A .key2 kifejezés kimenetét csővezetéken adjuk tovább a length bemenetének, amely nem meglepő módon a tömb elemeinek számát adja ki.
Ebben a példában a bemenő JSON adatot figyelmen kívül hagyjuk, és nincs hatással a kimenetre:
$ echo '{"answer": 42}' | jq '6 * 9'
54
Egy szűrő egynél több értéket is kiadhat.
Például a .[] szűrő a tömb minden elemét külön értékként adja ki:
$ jq -n -c '[1, 2, 3]'
[1,2,3]
$ jq -n -c '[1, 2, 3] | .[]'
1
2
3
Ha egy ilyen szűrőt egy másikba vezetsz, a második szűrő minden egyes értékre lefut:
$ jq -n -c '[1, 2, 3] | .[] | . * 2'
2
4
6
Ez olyan, mint az implicit iteráció.
Ha egyszer megérted ezt a technikát, rájössz, hogy a nagyon erős jq szűrők is lehetnek nagyon tömörek.
A zárójelekkel részkifejezéseket csoportosíthatsz, hogy érvényre juttasd a műveletek sorrendjét, akárcsak más nyelvekben.
A jq-ban néha meglepőnek tűnhet, hogy szükség van rájuk.
Tegyük fel például, hogy egy kételemű tömböt szeretnénk létrehozni: a 9 négyzetgyökét és az 1. hatványra emelt e-t.
A két külön kifejezés a 9 | sqrt és az 1 | exp.
Azt várjuk, hogy a kimenet a [3, 2.7...] tömb lesz
$ jq -n '[ 9|sqrt, 1|exp ]'
[
20.085536923187668,
2.718281828459045
]
Miért nem azt kaptuk, amire számítottunk?
A jq így értelmezi:
[ ((9|sqrt), 1) | exp ]
A jq kételemű folyamot épít (3 és 1), amelyeket egyenként megkap az exp.
Gondoskodnunk kell róla, hogy az exp csak egy számot kapjon bemenetként.
Más szóval el kell érnünk, hogy a csővezeték kiértékelése megelőzze a vesszőét.
$ jq -n '[ 9|sqrt, (1|exp) ]'
[
3,
2.718281828459045
]
Anélkül, hogy túl mélyre mennénk (a függvények egy másik feladat témáját képezik majd), íme néhány hasznos beépített függvény:
length
Ha egy tömböt kap bemenetként, adja ki a tömb elemeinek számát.
$ jq -n '[10, 20, 30, 40] | length'
4
+
Ez az operátor az operandusai típusától függően mást és mást tesz: összeadja a számokat, összefűzi a stringeket, hozzáfűzi a tömböket, egyesíti az objektumokat.
$ jq -c -n '
3 + 4,
"foo" + "bar",
["a", "b"] + ["c"],
{"m": 10} + {"n": 20}
'
7
"foobar"
["a","b","c"]
{"m":10,"n":20}
Az add egy függvény, amely egy tömböt kap, és egy olyan elemet ad vissza, amelyben az összes elem össze van adva a + szabályai szerint.
A [1, 2, 3] | add kimenete 6.
map
Ha bemenetként egy tömböt és argumentumként egy szűrőt kap, adjon ki egy tömböt, amelyben a szűrő minden elemre alkalmazva van
$ jq -c -n '[10, 20, 30, 40] | map(. / 5)'
[2,4,6,8]
select
Ha valamilyen bemenetet és argumentumként egy szűrőt kap:
null értéket, hanem tényleg semmilyen kimenetet)Például ha adott néhány szám, válaszd ki a 3-mal oszthatókat
$ jq -n 'range(10) | select(. % 3 == 0)'
0
3
6
9
Emlékezz rá, hogy a range számok folyamát adja ki.
A select minden számra egyszer hívódik meg.
Csak azok a számok jelennek meg a kimenetben, amelyek „átmennek” a kifejezésen.
Gyakran kell egy tömb elemeit kiválasztanod. Erre néhány mód kínálkozik.
A ["Anne", "Bob", "Cathy", "Dave"] bemenettel válaszd ki a 4 hosszúságú neveket.
használd a map és a select függvényt együtt
map(select(length == 4))
bontsd fel a tömböt elemekre, alkalmazd a select függvényt erre a folyamra, és gyűjtsd össze az eredményeket
[ .[] | select(length == 4) ]
A megjegyzések egy # karakterrel kezdődnek, és a sor végéig tartanak.
Hirtelen megkívántad a palacsintát. Modern, technikailag fogékony emberként JSON formátumban írod meg a palacsinta hozzávalóinak bevásárlólistáját. A lista felépítése a következő:
{
"name": "name of shopping list",
"ingredients": [ ...list of ingredients... ],
"optional ingredients": [ ...list of ingredients... ]
}
Egy hozzávalót JSON-objektumként ábrázolunk, például így:
{
"item": "flour",
"amount": {
"quantity": 2,
"unit": "cup"
}
}
Egy hozzávalónak lehet egy "substitute" nevű opcionális tulajdonsága, amelyben egy másik, helyette használható összetevő neve szerepel stringként.
Nézzük meg, hogyan vizsgálhatjuk meg a bevásárlólistát a jq segítségével!
Írj egy kifejezést, amely kiírja a bevásárlólista "name" elemét!
Csak a "required" hozzávalókat számold. Az opcionális hozzávalókat ne vedd bele.
Írj egy kifejezést, amely kiírja a cukor mennyiségét! Csak a számértékre van szükség.
Néhány hozzávaló helyettesíthető (ha nincs meg az X hozzávaló, használhatod helyette az Y-t). Adj ki egy JSON-objektumot, amely az ajánlott hozzávalót a helyettesítőjéhez rendeli. Az opcionális hozzávalókat is vedd bele a leképezésbe.
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) jq nyelvet 12 fogalom75 feladat segítségével, valódi emberi mentorálással, mindez ingyen.