Dans mon dernier article sur Habré, j'ai écrit sur la bibliothèque Jsqry , qui fournit un langage de requête simple et pratique (DSL) pour les objets JSON. Beaucoup de temps s'est écoulé depuis et la bibliothèque s'est également développée. Une autre raison de fierté - la bibliothèque a une couverture de code de 98% par les tests. Cependant, cet article ne la concerne pas entièrement.
Je pense que beaucoup d'entre vous connaissent l'outil jq
, qui est pratiquement la norme de facto pour travailler avec JSON dans la ligne de commande et les scripts. J'en étais également un utilisateur actif. Mais j'étais constamment préoccupé par la complexité injustifiée et la syntaxe peu intuitive des requêtes de cet utilitaire. Et pas moi seul, voici quelques citations de hacker news :
J'utilise jq depuis des années et je n'arrive toujours pas à le faire fonctionner comme je m'y attendais.
J'ai le même problème avec jq. Je dois utiliser mon google fu pour comprendre comment faire autre chose qu'une simple sélection.
Je ne sais pas quel serait le terme, modèle mental, mais je n'arrive pas à faire cliquer jq. Surtout parce que je n'en ai besoin que de temps en temps. C'est frustrant pour moi car cela me semble assez puissant.
Je sais que je pourrais ĂŞtre une opinion dissidente ici, mais je ne pourrai jamais comprendrejq
. Je peux gérerjq .
,jq .foo
etjq -r
, mais au-delà de ça, le DSL est juste opaque pour moi.
Disons-le simplement: jq est un outil incroyable, mais le DSL est tout simplement mauvais.
Ouais, je trouve jq similaire à l'écriture de regex: je dois toujours rechercher la syntaxe, ne la faire fonctionner qu'après une certaine confusion sur les raisons pour lesquelles mes modèles ne correspondent pas, puis oublier tout cela dans quelques jours, alors je dois le réapprendre plus tard.
Bref, vous l'avez probablement déjà deviné. J'ai une idée, pourquoi ne pas transformer ma bibliothèque JS en un exécutable en ligne de commande.Il y a une nuance ici. La bibliothèque est écrite en JS et son DSL repose également sur JS. Cela signifie que nous devons trouver un moyen de conditionner le programme et une partie du runtime JS dans un fichier exécutable autonome.
jsqry - Ă©dition GraalVM
Pour ceux qui ne sont pas encore dans le sujet (y en a-t-il vraiment encore? OO), permettez-moi de vous rappeler que GraalVM est une JVM tellement gonflée d'Oracle avec des fonctionnalités supplémentaires, dont les plus remarquables sont:
- JVM — Java, Javascript, Python, Ruby, R, ..
- AOT- — Java
- JIT- Java.
Graal , , -.
, 1. 2. — JS .
https://github.com/jsqry/jsqry-cli. , — deprecated. , . , 99 . - . , jq
3.7 Linux 64.
.
, Java + JS GraalVM.
App.java. , java- Apache Commons CLI.
java- javascript , src/main/resources.
. -
scripts.add(new String(Files.readAllBytes(Paths.get(jsFileResource.toURI()))));
( , native-image)
java.nio.file.FileSystemNotFoundException: Provider "resource" not installed
"" InputStream
scripts.add(new Scanner(jsFileResource.openStream()).useDelimiter("\\A").next());
, 100% Java .
java.awt.Graphics. GraalVM AWS Lambda .
jsqry — QuickJS edition
- JS QuickJS . qjsc
. ES2020. !
, CLI- jsqry
: https://github.com/jsqry/jsqry-cli2.
.
, jsqry
?
jsqry
( jq) JSON "" DSL.
— JS jsqry .
$ echo '[{"name":"John","age":30},
{"name":"Alice","age":25},
{"name":"Bob","age":50}]' | jsqry 'name'
[
"John",
"Alice",
"Bob"
]
$ echo '[{"name":"John","age":30},
{"name":"Alice","age":25},
{"name":"Bob","age":50}]' | jsqry -1 'name'
"John"
$ echo '[{"name":"John","age":30},{"name":"Alice","age":25},{"name":"Bob","age":50}]' \
| jsqry '[ _.age>=? && _.name.toLowerCase().startsWith(?) ]' --arg 30 --arg-str joh
[
{
"name": "John",
"age": 30
}
]
JSON pretty-printer
$ echo '[{"name":"John","age":30},{"name":"Alice","age":25},{"name":"Bob","age":50}]' \
| jsqry
[
{
"name": "John",
"age": 30
},
{
"name": "Alice",
"age": 25
},
{
"name": "Bob",
"age": 50
}
]
JSON . !
-
2, 100, 2 . . DSL.
$ echo '[1,2,3,4,5]' | jsqry '[_>2] {_+100} s(-_) [-2:]'
[
104,
103
]
JS
jsqry
JS- 1 , JS !
$ echo '["HTTP://EXAMPLE.COM/123",
"https://www.Google.com/search?q=test",
"https://www.YouTube.com/watch?v=_OBlgSz8sSM"]' \
| jsqry '{ _.match(/:\/\/([^\/]+)\//)[1].toLowerCase() }'
[
"example.com",
"www.google.com",
"www.youtube.com"
]
help-
$ jsqry
jsqry ver. 0.1.2
Usage: echo $JSON | jsqry 'query'
-1,--first return first result element
-h,--help print help and exit
-v,--version print version and exit
-c,--compact compact output (no pretty-print)
-u,--unquote unquote output string(s)
-as ARG,
--arg-str ARG supply string query argument
-a ARG,
--arg ARG supply query argument of any other type
jq
( ): 0.1.2.
, Linux x64 . , . .
, :
$ sudo bash -e -c "
wget https://github.com/jsqry/jsqry-cli2/releases/download/v0.1.2/jsqry-linux-amd64 -O/usr/local/bin/jsqry
chmod +x /usr/local/bin/jsqry
echo \"jsqry \$(jsqry -v) installed successfully\"
"
CLI-
GitHub - . - , . , CLI- , . , , , — .
"bash unit testing" BATS, ShellSpec, Bach , , ( 14 ), tush, .
tush
$ command --that --should --execute correctly
| expected stdout output
$ command --that --will --cause error
@ expected stderr output
? expected-exit-code
tush
$
, |
, @
?
— , . , $
, diff
. , diff . :
$ /bin/bash /home/xonix/proj/jsqry-cli2/tests.sh
--- tests.tush expected
+++ tests.tush actual
@@ -1,5 +1,5 @@
$ jsqry -v
-| 0.1.2
+| 0.1.1
$ jsqry -h
| jsqry ver. 0.1.1
!!! TESTS FAILED !!!
, , .
GitHub Action, , :
JSON
JSON . zvakanaka/color-json , StackOverflow . jq
. , null .
, .
npm- QuickJS
npm- jsqry
. package.json . npm i
. prepare-for-qjs.py, nodejs ES, QuickJS. jsqry-cli.js.
UTF-8 QuickJS
QuickJS stdin. , , QuickJS, . , UTF-8 JS-. , , QuickJS: twardoch/svgop.
"" , .
— tests.sh. , , .
— build.sh QuickJS, tests.sh tush
. — .
. ls -lh jsqry
. , , CLI- . , — , QuickJS.
652 KB. , , JS.
jq
. .