Aussi disponible en : English · Español · Português · العربية
Testeur JSONPath
Évaluez une requête JSONPath sur votre JSON et voyez les nœuds correspondants, leurs chemins normalisés, et si l'ordre du résultat est fixé par la norme.
Qu'est-ce que JSONPath ?
JSONPath est un langage de requête pour JSON, comme XPath l'est pour XML. Une expression telle que $.store.book[?@.price < 10].title pénètre dans un document et en extrait ce que vous voulez : tous les livres à moins de dix, et leur seul titre. On la retrouve dans Kubernetes et kubectl, dans des configurations d'intégration continue, dans des chaînes de traitement de journaux, dans des passerelles d'API et dans quantité de bibliothèques ayant besoin de désigner une partie d'une charge utile.
Pendant presque toute son existence, elle n'a eu aucune spécification. Née d'un billet de blog en 2007, elle a été implémentée par chacun à partir de cette description, et les implémentations divergeaient en silence : la même requête pouvait renvoyer des choses différentes, dans un autre ordre, selon le langage. Aucun document ne permettait de trancher lorsque deux d'entre elles s'opposaient.
La RFC 9535 a changé cela en février 2024. Ce testeur exécute une véritable implémentation de cette norme : collez une requête et un document, et vous obtenez les nœuds correspondants, le chemin normalisé de chacun, et une indication sur le caractère garanti ou non de l'ordre que vous avez sous les yeux.
Comment l'utiliser
- Écrivez une requête. Partez des exemples si vous le souhaitez : l'un filtre par prix, l'autre rassemble tous les prix du document, et deux montrent ce qui se passe quand l'ordre n'est pas fixé. Les résultats se mettent à jour à mesure que vous tapez.
- Collez votre JSON. N'importe quel document valide. S'il ne peut être analysé, l'outil le dit plutôt que de faire croire à un échec de la requête.
- Lisez les chemins et la note sur l'ordre. Chaque résultat porte son chemin normalisé, l'unique façon non ambiguë de désigner ce nœud. En dessous, l'outil indique si toute implémentation conforme renverrait ces nœuds dans cet ordre, ou si une autre est libre de diverger.
Ce que la norme tranche, et les deux choses qu'elle laisse ouvertes
La bonne nouvelle est l'ampleur de ce que la RFC 9535 fixe. L'expression implementation-defined n'y apparaît pas une seule fois. L'ordre du parcours descendant, la sémantique des tranches à pas négatif, ce que fait une comparaison quand un côté ne sélectionne rien : tout est spécifié, tout est vérifiable.
Il existe exactement deux endroits où l'ordre du résultat reste ouvert, et la spécification les nomme tous les deux au lieu de vous les laisser découvrir. Le premier est la sélection des membres d'un objet : les objets JSON n'ont pas d'ordre, un joker sur l'un d'eux peut donc revenir dans un sens ou dans l'autre. Les tableaux ne sont pas concernés — leur ordre est toujours préservé — ce qui est justement la moitié que l'on croit menacée.
Le second est un segment portant plus d'un sélecteur, comme [0,0] ou [*,*]. Cela produit chaque nœud correspondant une fois par sélecteur — réellement dupliqué, non dédupliqué — et l'entrelacement n'est pas fixé. Celui-ci vaut la peine d'être connu car la spécification prend soin de préciser que les implémentations ne renvoyant ce nœud qu'une fois ne sont pas conformes. Si vous comptiez sur une bibliothèque pour fusionner les doublons, ce comportement n'est pas la norme.
La règle que la plupart des anciennes implémentations enfreignent concerne les types. Une comparaison ne peut porter que sur un littéral, une requête singulière — qui ne peut sélectionner qu'un nœud au plus — ou une fonction renvoyant une valeur. Ainsi $[?@.* == 1] est une erreur de syntaxe, et non une comparaison qui ne correspondrait silencieusement à rien. Et un chemin ne sélectionnant rien produit une valeur particulière nommée Nothing, égale à elle seule : deux chemins absents se comparent comme égaux, tandis qu'un chemin absent n'est ni inférieur ni supérieur à un nombre. De la dérivation même des opérateurs dans la spécification, il suit que deux chemins absents se comparent aussi comme inférieurs ou égaux.
Comment ce moteur a été vérifié, et ce que cela ne prouve pas
La RFC 9535 est accompagnée d'une suite de conformité officielle, ce qui transforme en nombre la qualité d'une implémentation. Elle compte 703 tests et ce moteur les réussit tous. Ce chiffre est vérifié à la compilation, il ne peut donc pas pourrir en silence.
Un tiers de ce corpus — 247 tests — se compose de requêtes qui doivent être rejetées. C'est là qu'un analyseur permissif échoue, et cela représente une part considérable du travail : la norme est stricte sur les espaces, sur les endroits où une requête non singulière peut figurer, et sur les échappements licites à l'intérieur d'un nom entre guillemets. Accepter une requête malformée compte comme un échec, même si aucune réponse sensée n'était possible.
Un score parfait ne prouve pas la correction, et cette construction l'illustre bien. La spécification ne définit que deux opérateurs de comparaison et dérive les autres : a inférieur ou égal à b signifie a inférieur à b ou a égal à b. Comme deux Nothing se comparent comme égaux, deux Nothing doivent aussi se comparer comme inférieurs ou égaux. Une version écrite à la main de cet opérateur renvoyait false, et la suite de conformité a affiché 703 sur 703 avec ce défaut présent, car le corpus ne couvre pas ce cas. Il a été attrapé par des vérifications distinctes, dérivées du texte de la spécification et non de ses tests.
Les limites qu'il faut énoncer : l'outil analyse votre document avec l'analyseur JSON du navigateur, si bien qu'un nombre trop grand pour un double arrive déjà arrondi avant que la requête ne le voie ; la norme a beaucoup à dire sur les nombres interopérables, et rien de cela ne rattrape une valeur perdue à l'analyse. Les expressions régulières de match et search suivent la RFC 9485, un petit sous-ensemble sans groupes de capture, sans anticipation et sans références arrière ; un motif qui en emploie n'est pas une I-Regexp valide, et la fonction est définie pour renvoyer false plutôt que d'échouer.
Pourquoi est-ce gratuit ?
Le moteur tourne dans votre navigateur. Analyser une requête et parcourir un document ne coûte rien sur votre propre machine : il n'y a donc aucun serveur à financer ni compte à créer.
Rien de ce que vous collez n'est envoyé, conservé ni journalisé. Le JSON que vous déboguez est le plus souvent une charge utile réelle issue d'un vrai système, et la façon fiable de garder cela privé est de ne jamais le recevoir.