
JSONPath dans le navigateur : Une référence pratique et un testeur pour les patterns que vous utilisez vraiment
📷 Pixabay / PexelsJSONPath dans le navigateur : Une référence pratique et un testeur pour les patterns que vous utilisez vraiment
Arrêtez de deviner si votre requête JSONPath correspondra à ce que vous attendez. Un guide pratique des filtres, slices et de l'opérateur de descente récursive — avec un testeur gratuit.
Je travaille avec des APIs depuis assez longtemps pour me souvenir quand XML était le défaut et XPath était le langage de requête que tout le monde apprenait. JSONPath est l'équivalent JSON, et après des années à l'éviter (parce que je pouvais juste écrire du JavaScript, non ?), j'ai changé d'avis. Il y a trop d'endroits où JSONPath est le seul langage disponible — variables Postman, AWS Step Functions, sélecteurs Kubernetes, filtres Datadog — et être fluent fait gagner du temps réel.
Ce guide est la référence que j'aurais aimé avoir quand j'ai commencé. Nous couvrirons la syntaxe qui apparaît réellement en production, les pièges qui m'ont coûté des heures, et comment le Testeur JSONPath sur ToolBox Hubs vous laisse vérifier vos expressions avant de les coller où que ce soit de conséquent.
Ce qu'est JSONPath, rapidement
JSONPath est un langage de requête pour les documents JSON. Vous lui donnez une expression comme $.store.book[*].author et il retourne toutes les valeurs qui correspondent. Le $ est la racine, les points et crochets naviguent dans la structure, et des opérateurs spéciaux permettent de filtrer, slicer et traverser récursivement.
Si vous avez utilisé XPath pour XML, le modèle mental se transfère directement. Sinon, pensez-y comme à une version plus puissante de la notation pointée en JavaScript — qui peut exprimer "tous les livres avec un prix inférieur à 10$" ou "chaque auteur à n'importe quelle profondeur dans le document" en une seule ligne.
L'exemple canonique que tout le monde utilise vient de l'article original de Stefan Goessner :
{
"store": {
"book": [
{ "category": "fiction", "author": "Tolkien", "price": 22.99 },
{ "category": "reference", "author": "Rees", "price": 8.95 }
],
"bicycle": { "color": "red", "price": 19.95 }
}
}
$.store.book[*].author retourne ["Tolkien", "Rees"]. $..price retourne [22.99, 8.95, 19.95]. $.store.book[?(@.price < 10)] retourne le deuxième objet livre. C'est tout le jeu.
Les opérateurs que vous utiliserez 90% du temps
Il y a des dizaines d'opérateurs JSONPath. Cinq d'entre eux couvrent presque tout ce que vous écrirez en pratique.
$ — La racine
Chaque expression JSONPath commence par $. Elle fait référence au sommet du document. Vous pouvez techniquement l'omettre (certaines bibliothèques sont indulgentes) mais l'écrire explicitement clarifie l'intention.
.field — Accès enfant
Notation pointée standard. $.users.0.email parcourt depuis la racine vers le tableau users, choisit l'index 0, et lit email. Comme JavaScript sauf que le 0 fonctionne comme un nom de propriété.
[n] — Index de tableau
Notation entre crochets pour l'accès à un tableau, utile quand les indices sont dynamiques ou quand le nom du champ a des caractères spéciaux. $.users[0], $.users[-1] (dernier élément), $.users[0:3] (slice de 0 à 3 exclusif).
Les indices négatifs comptent depuis la fin. $.users[-1] est le dernier utilisateur. $.users[-3:] donne les trois derniers. Ce n'est pas supporté dans toutes les implémentations — RFC 9535 le standardise, mais vérifiez votre bibliothèque si vous en dépendez.
[*] — Wildcard
Correspond à tous les éléments dans un tableau ou toutes les valeurs dans un objet. $.users[*].email retourne l'email de chaque utilisateur. $.config.* retourne chaque valeur dans l'objet config. Combiné avec l'accès aux propriétés, c'est comme cela que vous aplatissez les structures courantes.
..field — Descente récursive
L'opérateur le plus puissant et celui que j'utilise le plus. $..price trouve chaque champ price n'importe où dans le document, peu importe la profondeur d'imbrication. Utile quand vous ne connaissez pas ou ne vous souciez pas de la structure exacte.
La descente ne se soucie pas du path — elle trouve simplement tout ce qui correspond au pattern. Cela la rend excellente pour l'exploration ad hoc des données ("cette réponse contient-elle des IDs d'utilisateur ?") et dangereuse si vos données ont le même nom de clé apparaissant dans différents contextes (un champ name sur les utilisateurs et un champ name sur les rôles correspondront tous deux à $..name).
Filtres : Là où les gens se bloquent
Les expressions de filtre sont écrites [?(...)] où le contenu est une expression booléenne évaluée contre chaque élément dans un tableau. À l'intérieur du filtre, @ fait référence à l'élément actuel.
$.store.book[?(@.price < 10)]
$.users[?(@.role == 'admin')]
$.events[?(@.timestamp > 1700000000)]
Le @ est la partie qui fait trébucher les gens. C'est l'équivalent de this ou de l'élément actuel dans un forEach. Sans cela, le filtre ne peut référencer aucun champ — [?(price < 10)] ne fonctionne pas car price n'est pas défini ; le moteur ne sait pas qu'il doit regarder à l'intérieur de l'élément actuel.
Opérateurs de comparaison
Universels à travers les bibliothèques : ==, !=, <, >, <=, >=.
Le côté droit peut être un littéral : un nombre (@.age > 18), une chaîne entre guillemets simples (@.role == 'admin'), une chaîne entre guillemets doubles, true, false, ou null.
Ce qui n'est PAS universel : comparer deux champs entre eux (@.price > @.cost), correspondance regex (@.email =~ /.*@example\.com/), appels de fonction comme length() ou match(). Certaines bibliothèques les supportent ; beaucoup non. Le Testeur JSONPath sur ToolBox Hubs supporte les comparaisons de base contre des valeurs littérales, ce qui couvre la grande majorité des requêtes réelles.
Combinaisons booléennes
Les implémentations standard supportent && et || pour combiner des conditions :
$.products[?(@.in_stock == true && @.price < 50)]
$.events[?(@.severity == 'error' || @.severity == 'critical')]
Si vous vous retrouvez à écrire de la logique booléenne complexe en JSONPath, c'est généralement un signal pour passer à du vrai code — votre futur vous lisant l'expression dans six mois vous remerciera. JSONPath brille pour les sélections simples ; la logique métier complexe appartient à un vrai langage.
Slices : Pour quand vous n'avez besoin que de certains éléments
[start:end:step] fonctionne exactement comme le slicing Python.
[0:5]— les 5 premiers éléments[5:]— depuis l'index 5 et au-delà[:3]— les 3 premiers éléments (identique à[0:3])[-3:]— les 3 derniers éléments[::2]— un élément sur deux[::-1]— inversé (pas supporté partout)
Le slicing est une des parties les plus propres de JSONPath. C'est un port direct de Python et il se comporte de façon prévisible. Je l'utilise beaucoup pour les patterns "donne-moi les N premiers résultats" ou "donne-moi tout sauf le premier".
Patterns qui apparaissent vraiment au travail
La théorie c'est bien ; regardons les vraies requêtes.
Filtrer les réponses d'API
Votre API retourne des résultats paginés et vous voulez trouver des éléments spécifiques. JSONPath dans votre framework de test ou Postman :
$.data[?(@.status == 'active')].id
Retourne les IDs de tous les éléments actifs. Si l'API n'a pas de paramètre "filter by status", c'est plus rapide que de transformer dans le code.
Extraire des valeurs de payloads webhook
Vous traitez des webhooks de Stripe, GitHub ou similaires, et vous devez attraper des champs spécifiques. JSONPath dans les règles AWS EventBridge, Step Functions ou Logic Apps :
$.detail.payload.items[*].sku
Retourne le SKU de chaque élément dans une commande. Les outils de workflow cloud reposent sur JSONPath car c'est déclaratif et inspectable, là où JavaScript embarqué serait un fardeau de sécurité et de maintenabilité.
Trouver des éléments dans des données profondément imbriquées
Vous ne connaissez pas la structure exacte mais vous savez qu'il y a un ID d'utilisateur quelque part :
$..userId
Retourne chaque champ userId dans le document, indépendamment de la profondeur d'imbrication. Utile pour l'exploration lors du travail avec des réponses d'API inconnues ou des intégrations tierces.
Valider des contraintes type schema
Vous devez vérifier que tous les éléments dans une liste ont un champ spécifique :
$.users[?(!@.email)]
Retourne les utilisateurs sans email. Si le résultat est vide, vos données sont propres. Ce pattern fonctionne bien dans les scripts de test CI où vous parsez une sortie JSON et faites des assertions sur sa structure.
Les pièges (une liste personnelle)
Voici les choses qui m'ont coûté des heures.
Le @ dans les filtres est obligatoire. Écrire [?(price < 10)] au lieu de [?(@.price < 10)] est l'erreur la plus courante. Sans @, le moteur ne sait pas que price fait référence à un champ sur l'élément actuel.
Les filtres retournent les éléments correspondants, pas le champ sur lequel vous avez filtré. $..book[?(@.price < 10)] retourne des objets livre, pas des prix. Pour obtenir juste les prix : $..book[?(@.price < 10)].price.
Les guillemets comptent à l'intérieur des expressions. Utilisez des guillemets simples à l'intérieur des chaînes JSONPath pour éviter de confondre le langage environnant. Dans un fichier de configuration JSON votre JSONPath est une valeur de chaîne, donc le JSONPath lui-même utilise des guillemets simples : "$.users[?(@.role == 'admin')]". Les mélanger crée des erreurs de parsing.
La descente récursive trouve des correspondances fantômes. $..name correspondra à chaque champ name, y compris ceux dans des objets imbriqués non liés. Si vous avez des champs name d'utilisateur et des champs name de produit dans le même document, cela retournera les deux. Soyez spécifique quand cela compte.
Index 0 vs. propriété '0'. $.items[0] fonctionne sur les tableaux. $.items.0 peut ou non fonctionner — la plupart des parsers le rejettent pour les tableaux (c'est uniquement entre crochets) mais l'acceptent comme nom de propriété sur les objets. Restez avec les crochets pour l'accès aux tableaux.
Les résultats vides ne sont pas des erreurs. Si votre JSONPath ne correspond à rien, vous obtenez un tableau vide [], pas une exception. C'est le comportement correct, mais cela peut cacher des fautes de frappe. Si vous attendiez des résultats et n'en avez aucun, vérifiez le path.
RFC 9535 vs. bibliothèques de l'ère Goessner
L'article original de 2007 qui a défini JSONPath était informel — il décrivait la syntaxe avec des exemples mais ne spécifiait pas formellement le comportement dans les cas limites. Différentes implémentations de bibliothèques ont fait différents choix, et au fil des années les différences se sont accumulées.
En 2024, RFC 9535 a été publié comme la spec officielle. Elle standardise la syntaxe et la sémantique, particulièrement autour de :
- Grammaire des expressions de filtre
- Extensions de fonction (
length,count,match,search,value) - Paths normalisés en sortie (chaque résultat inclut sa localisation)
- Profil I-Regexp pour la correspondance regex
Si vous démarrez un nouveau projet, préférez les bibliothèques qui ciblent RFC 9535 — jsonpath-rfc9535 pour Node, ports Python jsonpath-rfc9535, outil CLI jp. Si vous maintenez du code existant, vous êtes probablement sur une implémentation de l'ère Goessner ; c'est OK, sachez juste que les différences existent.
Le Testeur JSONPath sur ToolBox Hubs implémente les opérateurs les plus courants qui fonctionnent de manière cohérente à travers les implémentations. Il est intentionnellement conservateur sur la syntaxe de filtre pour éviter de tester des choses qui ne fonctionneront pas dans votre environnement cible.
Là où JSONPath perd face à jq
Je vous tromperais si je ne mentionnais pas jq.
JSONPath est bon pour trouver des valeurs dans JSON. jq est bon pour trouver ET transformer JSON. Si vous avez besoin de :
- Projeter des objets vers une forme différente (
.users | map({id, email})) - Agréger des valeurs (
map(.price) | add) - Composer plusieurs opérations
- Gérer une logique conditionnelle complexe
jq est dramatiquement meilleur. JSONPath n'a pas d'agrégation, pas de map/reduce, et pas de composition de fonctions. Ce ne sont pas des bugs — ce sont des décisions de portée. JSONPath est un langage de requête. jq est un langage de transformation.
Le bon outil dépend de votre environnement. JSONPath est partout parce qu'il est simple à embarquer (pas de dépendances, juste un parser de chaîne). jq nécessite un binaire et est plus difficile à utiliser dans les contextes navigateur ou les environnements contraints. Dans un test Postman ou un mapping d'entrée Step Function, vous n'avez que JSONPath. Dans un pipeline shell ou une transformation de données côté serveur, jq est généralement meilleur.
Un workflow pratique
Voici comment j'utilise réellement JSONPath maintenant :
-
J'ouvre la réponse d'API ou le document JSON dans le Formateur JSON pour le rendre lisible.
-
J'identifie la ou les valeurs que je veux extraire. Habituellement je peux tracer le path mentalement : "tableau users, élément N, champ role, égal à admin."
-
J'ouvre le Testeur JSONPath, je colle le JSON, et j'écris l'expression. J'itère jusqu'à ce qu'elle retourne exactement ce que je veux.
-
Je copie l'expression qui fonctionne là où elle doit vivre — test Postman, AWS Step Function, sélecteur Kubernetes.
-
Si je construis quelque chose de plus complexe (transformation, agrégation), je passe à jq.
Ce workflow coupe des heures de débogage "pourquoi mon JSONPath ne correspond pas" des intégrations. Le testeur est l'étape manquante que la plupart des tutoriels sautent — ils montrent la syntaxe et supposent que vous pouvez l'écrire correctement du premier coup. Vous ne pouvez généralement pas, surtout avec les filtres.
Recommandations d'outils pour le workflow JSON plus large
JSONPath est un outil dans un workflow JSON. L'associer avec des utilitaires connexes rend tout le pipeline plus fluide :
- Formateur JSON — pretty-print avant de requêter ; le JSON minifié est illisible
- JSON Diff — quand JSONPath retourne des résultats différents entre deux réponses, faites-en le diff pour voir ce qui a changé
- JSON to TypeScript — générer des types TypeScript à partir d'un échantillon, puis utiliser le type pour écrire JSONPath qui correspond au schéma
- Générateur de Schéma JSON — produire un JSON Schema pour la validation ; complémentaire à JSONPath qui est pour la requête
Le Testeur JSONPath est gratuit, navigateur uniquement, et n'envoie jamais votre JSON nulle part. Coller, requêter, itérer, copier. C'est la boucle.
Notes finales
JSONPath n'est pas glamour. Ce n'est pas le langage que les gens sont enthousiastes d'apprendre. Mais passer une heure à devenir fluent rapporte sur des années de débogage d'API, configuration de workflow cloud, et exploration de données. La syntaxe est suffisamment petite pour mémoriser les patterns courants. Les pièges sont suffisamment prévisibles pour les internaliser.
Si vous y êtes nouveau : commencez avec les patterns de base ($.field, $..field, $.array[*], [?(@.field == 'value')]) et évitez la complexité des filtres jusqu'à ce que vous ayez utilisé le simple pendant un moment. La plupart des requêtes du monde réel sont simples. La complexité vient des cas limites qui sont généralement mieux résolus avec du code.