Aller au contenu principal

2.1. Overview (Vue d'ensemble)

2.1. Overview (Vue d'ensemble)

Une expression JSONPath est une chaîne qui, appliquée à une valeur JSON (l'argument de requête, query argument), sélectionne zéro ou plusieurs nœuds de l'argument et produit en sortie ces nœuds sous forme de nodelist (liste de nœuds).

Une requête DOIT être encodée en UTF-8. La grammaire des requêtes donnée dans ce document suppose que sa forme UTF-8 est d'abord décodée en valeurs scalaires Unicode comme décrit dans [RFC3629] ; des approches d'implémentation menant à un résultat équivalent sont possibles.

Une chaîne destinée à servir de requête JSONPath doit être bien formée (well-formed) et valide (valid). Une chaîne est une requête JSONPath bien formée si elle est conforme à la syntaxe ABNF de ce document. Une requête JSONPath bien formée est valide si elle satisfait aussi les deux exigences sémantiques posées par ce document, qui sont les suivantes :

  1. Les nombres entiers dans la requête JSONPath pertinents pour le traitement JSONPath (par ex. valeurs d'indice et pas) DOIVENT être dans la plage des valeurs entières exactes définies pour Internet JSON (I-JSON) (voir la section 2.2 de [RFC7493]), à savoir dans l'intervalle [-(2^53)+1, (2^53)-1].

  2. Les utilisations d'extensions de fonctions DOIVENT être bien typées (well-typed), comme décrit à la section 2.4.3.

Une implémentation JSONPath DOIT lever une erreur pour toute requête qui n'est pas bien formée et valide. Le caractère bien formé et la validité des requêtes JSONPath sont indépendants de la valeur JSON à laquelle la requête est appliquée. Aucune autre erreur relative au caractère bien formé et à la validité d'une requête JSONPath ne peut être levée lors de l'application de la requête à une valeur. Ceci sépare clairement les erreurs de bien-formé / validité dans la requête des incohérences pouvant réellement provenir de défauts dans les données.

Les écarts entre la structure attendue par une requête valide et la structure trouvée dans les données peuvent conduire à des résultats de requête vides, ce qui peut être inattendu et indiquer des bogues dans l'un ou l'autre. Les implémentations JSONPath peuvent donc souhaiter fournir au développeur d'application des diagnostics aidant à trouver la cause de résultats vides.

Évidemment, une implémentation peut encore échouer lors de l'exécution d'une requête JSONPath, par ex. par épuisement des ressources, mais ce n'est pas modélisé dans ce document. Cependant, l'implémentation NE DOIT PAS dysfonctionner silencieusement. Plus précisément, si une requête JSONPath valide est évaluée sur une valeur structurée dont la taille est trop grande pour traiter correctement la requête (par ex. en exigeant le traitement de nombres hors de la plage des valeurs exactes), l'implémentation DOIT fournir une indication de débordement.

(Les lecteurs familiers du modèle d'erreur HTTP peuvent penser aux erreurs de type 400 en considérant le bien-formé et la validité, et reconnaître l'épuisement des ressources et erreurs associées comme comparables aux erreurs de type 500.)

2.1.1. Syntax (Syntaxe)

Syntaxiquement, une requête JSONPath consiste en un identifiant racine ($), qui représente une nodelist contenant le nœud racine de l'argument de requête, suivi d'une séquence éventuellement vide de segments (segments).

jsonpath-query      = root-identifier segments
segments = *(S segment)
B                   = %x20 /    ; Space
%x09 / ; Horizontal tab
%x0A / ; Line feed or New line
%x0D ; Carriage return
S = *B ; optional blank space

La syntaxe et la sémantique des segments sont définies à la section 2.5.

2.1.2. Semantics (Sémantique)

Dans ce document, la sémantique d'une requête JSONPath définit les résultats requis et ne prescrit pas le fonctionnement interne d'une implémentation. Ce document peut décrire la sémantique de façon procédurale pas à pas ; toutefois, de telles descriptions ne sont normatives que dans le sens où toute implémentation DOIT produire un résultat identique, et non dans le sens où les implémenteurs seraient tenus d'utiliser les mêmes algorithmes.

La sémantique est qu'une requête valide est exécutée sur une valeur (l'argument de requête) et produit une nodelist (c'est-à-dire une liste de zéro ou plusieurs nœuds de la valeur).

La requête est un identifiant racine suivi d'une séquence de zéro ou plusieurs segments, chacun étant appliqué au résultat de l'identifiant racine ou du segment précédent et fournissant l'entrée au segment suivant. Ces résultats et entrées prennent la forme de nodelists.

La nodelist résultant de l'identifiant racine contient un seul nœud (l'argument de requête). La nodelist résultant du dernier segment est présentée comme le résultat de la requête. Selon l'API spécifique, elle peut être présentée comme un tableau des valeurs JSON aux nœuds, un tableau de chemins normalisés référençant les nœuds, ou les deux — ou toute autre représentation souhaitée par l'implémentation. Note : Une nodelist vide est un résultat de requête valide.

Un segment opère sur chacun des nœuds de sa nodelist d'entrée à tour de rôle, et les nodelists résultantes sont concaténées dans l'ordre de la nodelist d'entrée dont elles proviennent pour produire le résultat du segment. Un nœud peut être sélectionné plus d'une fois et apparaît ce nombre de fois dans la nodelist. Les nœuds dupliqués ne sont pas supprimés.

Un segment syntaxiquement valide NE DOIT PAS produire d'erreurs lors de l'exécution de la requête. Cela signifie que certaines opérations qui pourraient être considérées comme erronées, comme l'utilisation d'un indice hors de la plage d'un tableau, aboutissent simplement à moins de nœuds sélectionnés. (Une discussion supplémentaire de cette propriété se trouve dans l'introduction de la section 2.1.)

Conséquence de cette approche : si l'un des segments produit une nodelist vide, alors toute la requête produit une nodelist vide.

Si la sémantique d'une requête laisse à une implémentation le choix entre plusieurs ordres possibles, une implémentation particulière peut produire des ordres distincts lors d'exécutions successives de la requête.

2.1.3. Example (Exemple)

Considérons cet exemple. Avec l'argument de requête {"a":[{"b":0},{"b":1},{"c":2}]}, la requête $.a[*].b sélectionne la liste de nœuds suivante (notée ici par leurs valeurs) : 0, 1.

La requête consiste en $ suivi de trois segments : .a, [*], et .b.

D'abord, $ produit une nodelist constituée uniquement de l'argument de requête.

Ensuite, .a sélectionne à partir de tout nœud d'entrée objet et sélectionne le nœud de toute valeur de membre du nœud d'entrée correspondant au nom de membre "a". Le résultat est encore une liste contenant un seul nœud : [{"b":0},{"b":1},{"c":2}].

Ensuite, [*] sélectionne tous les éléments du nœud tableau d'entrée. Le résultat est une liste de trois nœuds : {"b":0}, {"b":1}, et {"c":2}.

Enfin, .b sélectionne à partir de tout nœud d'entrée objet avec un nom de membre b et sélectionne le nœud de la valeur de membre du nœud d'entrée correspondant à ce nom. Le résultat est une liste contenant 0, 1. C'est la concaténation de trois listes : deux de longueur un contenant respectivement 0 et 1, et une de longueur zéro.