Aller au contenu principal

2.3. Selectors (Sélecteurs)

2.3. Selectors (Sélecteurs)

Les sélecteurs n'apparaissent qu'à l'intérieur des segments enfants (section 2.5.1) et des segments descendants (section 2.5.2).

Un sélecteur produit une nodelist constituée de zéro ou plusieurs enfants de la valeur d'entrée.

Il existe plusieurs types de sélecteurs qui produisent des enfants d'objets, des enfants de tableaux, ou des enfants d'objets ou de tableaux indistinctement.

selector            = name-selector /
wildcard-selector /
slice-selector /
index-selector /
filter-selector

La syntaxe et la sémantique de chaque type de sélecteur sont définies ci-dessous.

2.3.1. Name Selector (Sélecteur de nom)

2.3.1.1. Syntax (Syntaxe)

Un sélecteur de nom '<name>' sélectionne au plus une valeur de membre d'objet.

Contrairement à JSON, la syntaxe JSONPath permet d'entourer les chaînes de guillemets simples ou doubles.

name-selector       = string-literal
string-literal      = %x22 *double-quoted %x22 /     ; "string"
%x27 *single-quoted %x27 ; 'string'
double-quoted       = unescaped /
%x27 / ; '
ESC %x22 / ; \"
ESC escapable
single-quoted       = unescaped /
%x22 / ; "
ESC %x27 / ; \'
ESC escapable
ESC                 = %x5C                           ; \ backslash
unescaped           = %x20-21 /                      ; see RFC 8259
; omit 0x22 "
%x23-26 /
; omit 0x27 '
%x28-5B /
; omit 0x5C \
%x5D-D7FF /
; skip surrogate code points
%xE000-10FFFF
escapable           = %x62 / ; b BS backspace U+0008
%x66 / ; f FF form feed U+000C
%x6E / ; n LF line feed U+000A
%x72 / ; r CR carriage return U+000D
%x74 / ; t HT horizontal tab U+0009
"/" / ; / slash (solidus) U+002F
"\" / ; \ backslash (reverse solidus) U+005C
(%x75 hexchar) ; uXXXX U+XXXX
hexchar             = non-surrogate /
(high-surrogate "\" %x75 low-surrogate)
non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") 3HEXDIG) /
("D" %x30-37 2HEXDIG )
high-surrogate = "D" ("8"/"9"/"A"/"B") 2HEXDIG
low-surrogate = "D" ("C"/"D"/"E"/"F") 2HEXDIG
HEXDIG              = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"

Notes :

  • Les chaînes entre guillemets doubles suivent la syntaxe des chaînes JSON (section 7 de [RFC8259]) ; les chaînes entre guillemets simples suivent un schéma analogue. Aucune tentative d'amélioration de cette syntaxe n'a été faite ; ainsi, s'il faut échapper des caractères de valeur scalaire au-dessus de 0xFFFF, tels qu'U+1F041 (« 🁁 », DOMINO TILE HORIZONTAL-02-02), ils doivent être représentés par une paire d'échappements de substitution (« \uD83C\uDC41 » dans ce cas).

  • Les caractères alphabétiques dans les chaînes entre guillemets sont insensibles à la casse en ABNF, donc chacun des chiffres hexadécimaux dans les échappements \u (comme spécifié dans les règles référencées par hexchar) peut être en minuscules ou majuscules, tandis que le u dans \u doit être en minuscules (indiqué comme %x75).

2.3.1.2. Semantics (Sémantique)

Une chaîne de sélecteur de nom DOIT être convertie en nom de membre M en retirant les guillemets entourants et en remplaçant chaque séquence d'échappement par son caractère Unicode équivalent, comme indiqué au tableau 4 :

Séquence d'échappementCaractère UnicodeDescription
\bU+0008BS retour arrière
\tU+0009HT tabulation horizontale
\nU+000ALF saut de ligne
\fU+000CFF saut de page
\rU+000DCR retour chariot
"U+0022guillemet
'U+0027apostrophe
/U+002Fbarre oblique (solidus)
\U+005Ccontre-oblique (reverse solidus)
\uXXXXvoiréchappement hexadécimal
section 2.3.1.1

Tableau 4 : Remplacements des séquences d'échappement

Appliquer le sélecteur de nom à un nœud objet sélectionne une valeur de membre dont le nom est égal au nom de membre M ou ne sélectionne rien s'il n'existe pas une telle valeur de membre. Rien n'est sélectionné à partir d'une valeur qui n'est pas un objet.

Note : Le traitement du sélecteur de nom exige de comparer la chaîne de nom de membre M aux chaînes de nom de membre dans le JSON auquel le sélecteur est appliqué. Deux chaînes DOIVENT être considérées égales si et seulement si elles sont des séquences identiques de valeurs scalaires Unicode. En d'autres termes, des opérations de normalisation NE DOIVENT PAS être appliquées ni à la chaîne de nom de membre M provenant du JSONPath ni aux chaînes de nom de membre dans le JSON avant comparaison.

2.3.1.3. Examples (Exemples)

JSON :

{
"o": {"j j": {"k.k": 3}},
"'": {"@": 2}
}

Requêtes :

Les exemples du tableau 5 montrent le sélecteur de nom utilisé par des segments enfants.

RequêteRésultatChemins de résultatCommentaire
$.o['j j']{"k.k":$['o']['j j']Valeur nommée
3}dans un objet
imbriqué
$.o['j j']['k.k']3$['o']['j j']['k.k']Imbrication
plus profonde
$.o["j j"]["k.k"]3$['o']['j j']['k.k']Délimiteur
différent dans
la requête,
chemin normalisé
inchangé
$["'"]["@"]2$[''']['@']Noms de membres
inhabituels

Tableau 5 : Exemples de sélecteur de nom

2.3.2. Wildcard Selector (Sélecteur joker)

2.3.2.1. Syntax (Syntaxe)

Le sélecteur joker consiste en un astérisque.

wildcard-selector   = "*"

2.3.2.2. Semantics (Sémantique)

Un sélecteur joker sélectionne les nœuds de tous les enfants d'un objet ou d'un tableau. L'ordre dans lequel les enfants d'un objet apparaissent dans la nodelist résultante n'est pas prescrit, car les objets JSON sont non ordonnés. Les enfants d'un tableau apparaissent dans l'ordre du tableau dans la nodelist résultante.

Notez que les enfants d'un objet sont ses valeurs de membre, pas ses noms de membres.

Le sélecteur joker ne sélectionne rien à partir d'une valeur JSON primitive (c'est-à-dire un nombre, une chaîne, true, false ou null).

2.3.2.3. Examples (Exemples)

JSON :

{
"o": {"j": 1, "k": 2},
"a": [5, 3]
}

Requêtes :

Les exemples du tableau 6 montrent le sélecteur joker utilisé par un segment enfant.

RequêteRésultatCheminsCommentaire
de résultat
$[*]{"j": 1,$['o']Valeurs d'objet
"k": 2}$['a']
[5, 3]
$.o[*]1$['o']['j']Valeurs d'objet
2$['o']['k']
$.o[*]2$['o']['k']Résultat
1$['o']['j']alternatif
$.o[*,1$['o']['j']Ordre non déterministe
*]2$['o']['k']
2$['o']['k']
1$['o']['j']
$.a[*]5$['a'][0]Éléments de tableau
3$['a'][1]

Tableau 6 : Exemples de sélecteur joker

L'exemple ci-dessus avec la requête $.o[*, *] montre que le sélecteur joker peut produire des nodelists dans des ordres distincts à chaque fois qu'il apparaît dans le segment enfant lorsqu'il est appliqué à un nœud objet avec deux membres ou plus (mais pas lorsqu'il est appliqué à des nœuds objet avec moins de deux membres ou à des nœuds tableau).

2.3.3. Index Selector (Sélecteur d'indice)

2.3.3.1. Syntax (Syntaxe)

Un sélecteur d'indice <index> correspond à au plus une valeur d'élément de tableau.

index-selector      = int                        ; decimal integer
int                 = "0" /
(["-"] DIGIT1 *DIGIT) ; - optional
DIGIT1 = %x31-39 ; 1-9 non-zero digit

Appliquer le sélecteur d'indice numérique sélectionne l'élément correspondant. JSONPath permet qu'il soit négatif (voir la section 2.3.3.2).

Pour être valide, la valeur du sélecteur d'indice DOIT être dans la plage de valeurs exactes I-JSON (voir la section 2.1).

Notes :

  • Un sélecteur d'indice est un entier (en base 10, comme les nombres JSON).

  • Comme pour les nombres JSON, la syntaxe n'autorise pas d'entiers de style octal avec zéros en tête, tels que 01 ou -01.

2.3.3.2. Semantics (Sémantique)

Un sélecteur d'indice non négatif appliqué à un tableau sélectionne un élément de tableau en utilisant un indice à base zéro. Par exemple, le sélecteur 0 sélectionne le premier, et le sélecteur 4 le cinquième élément d'un tableau suffisamment long. Rien n'est sélectionné, et ce n'est pas une erreur, si l'indice est hors de la plage du tableau. Rien n'est sélectionné à partir d'une valeur qui n'est pas un tableau.

Un sélecteur d'indice négatif compte depuis la fin du tableau vers l'arrière, obtenant un sélecteur d'indice non négatif équivalent en ajoutant la longueur du tableau à l'indice négatif. Par exemple, le sélecteur -1 sélectionne le dernier, et le sélecteur -2 l'avant-dernier élément d'un tableau d'au moins deux éléments. Comme pour les indices non négatifs, ce n'est pas une erreur si un tel élément n'existe pas ; cela signifie simplement qu'aucun élément n'est sélectionné.

2.3.3.3. Examples (Exemples)

JSON :

["a","b"]

Requêtes :

Les exemples du tableau 7 montrent le sélecteur d'indice utilisé par un segment enfant.

RequêteRésultatChemins de résultatCommentaire
$[1]"b"$[1]Élément de tableau
$[-2]"a"$[0]Élément de tableau, depuis la fin

Tableau 7 : Exemples de sélecteur d'indice

2.3.4. Array Slice Selector (Sélecteur de tranche de tableau)

2.3.4.1. Syntax (Syntaxe)

Le sélecteur de tranche de tableau a la forme <start>:<end>:<step>. Il correspond à des éléments de tableaux en commençant à l'indice <start> et en finissant à (mais sans inclure) <end>, en incrémentant par pas step avec une valeur par défaut de 1.

slice-selector      = [start S] ":" S [end S] [":" [S step ]]

start = int ; inclus dans la sélection
end = int ; non inclus dans la sélection
step = int ; défaut : 1

Le sélecteur de tranche consiste en trois entiers décimaux optionnels séparés par des deux-points. Le second deux-points peut être omis lorsque le troisième entier est omis.

Pour être valide, les entiers fournis DOIVENT être dans la plage de valeurs exactes I-JSON (voir la section 2.1).

2.3.4.2. Semantics (Sémantique)

Le sélecteur de tranche s'inspire de l'opérateur de tranche proposé pour ECMAScript 4 (ES4), jamais publié, et de celui de Python.

2.3.4.2.1. Informal Introduction (Introduction informelle)

Cette section est informative.

La découpe de tableaux s'inspire du comportement de la méthode Array.prototype.slice du langage JavaScript, telle que définie par la norme ECMA-262 [ECMA-262], avec l'ajout du paramètre step, inspiré de l'expression de tranche Python.

L'expression de tranche start:end:step sélectionne des éléments aux indices commençant à start, en incrémentant de step, et se terminant avec end (qui est lui-même exclu). Ainsi, par exemple, l'expression 1:3 (où step vaut 1 par défaut) sélectionne les éléments aux indices 1 et 2 (dans cet ordre), tandis que 1:5:2 sélectionne les éléments aux indices 1 et 3.

Lorsque step est négatif, les éléments sont sélectionnés en ordre inverse. Ainsi, par exemple, 5:1:-2 sélectionne les éléments aux indices 5 et 3 (dans cet ordre), et ::-1 sélectionne tous les éléments d'un tableau en ordre inverse.

Lorsque step vaut 0, aucun élément n'est sélectionné. (C'est le seul cas qui diffère du comportement de Python, qui lève une erreur dans ce cas.)

La section suivante spécifie le comportement entièrement, sans dépendre du comportement JavaScript ou Python.

2.3.4.2.2. Normative Semantics (Sémantique normative)

Une expression de tranche sélectionne un sous-ensemble des éléments du tableau d'entrée dans le même ordre que le tableau ou l'ordre inverse, selon le signe du paramètre step. Elle ne sélectionne aucun nœud à partir d'un nœud qui n'est pas un tableau.

Une tranche est définie par les deux paramètres de tranche start et end, et un incrément d'itération step. Chacun de ces paramètres est optionnel. Dans le reste de cette section, len désigne la longueur du tableau d'entrée.

La valeur par défaut de step est 1. Les valeurs par défaut de start et end dépendent du signe de step, comme indiqué au tableau 8.

Conditionstartend
step >= 00len
step < 0len - 1-len - 1

Tableau 8 : Valeurs par défaut start et end pour la tranche de tableau

Les paramètres d'expression de tranche start et end ne sont pas directement utilisables comme bornes de tranche et doivent d'abord être normalisés. La normalisation à cette fin est définie comme :

FUNCTION Normalize(i, len): IF i >= 0 THEN RETURN i ELSE RETURN len + i END IF

Le résultat de l'expression d'indice de tableau i appliquée à un tableau de longueur len est le résultat de l'expression de découpe Normalize(i, len):Normalize(i, len)+1:1.

Les paramètres d'expression de tranche start et end servent à dériver les bornes inférieure et supérieure de tranche. La direction de l'itération, définie par le signe de step, détermine lequel des paramètres est la borne inférieure et lequel est la borne supérieure :

FUNCTION Bounds(start, end, step, len): n_start = Normalize(start, len) n_end = Normalize(end, len)

IF step >= 0 THEN lower = MIN(MAX(n_start, 0), len) upper = MIN(MAX(n_end, 0), len) ELSE upper = MIN(MAX(n_start, -1), len-1) lower = MIN(MAX(n_end, -1), len-1) END IF

RETURN (lower, upper)

L'expression de tranche sélectionne des éléments dont les indices sont entre les bornes inférieure et supérieure. Dans le pseudo-code suivant, a(i) est le (i+1)-ième élément du tableau a (c'est-à-dire a(0) est le premier élément, a(1) le second, etc.).

IF step > 0 THEN

i = lower WHILE i < upper: SELECT a(i) i = i + step END WHILE

ELSE if step < 0 THEN

i = upper WHILE lower < i: SELECT a(i) i = i + step END WHILE

END IF

Lorsque step = 0, aucun élément n'est sélectionné, et le tableau résultat est vide.

2.3.4.3. Examples (Exemples)

JSON :

["a", "b", "c", "d", "e", "f", "g"]

Requêtes :

Les exemples du tableau 9 montrent le sélecteur de tranche utilisé par un segment enfant.

RequêteRésultatCheminsCommentaire
de résultat
$[1:3]"b"$[1]Tranche avec
"c"$[2]pas par défaut
$[5:]"f"$[5]Tranche sans
"g"$[6]indice de fin
$[1:5:2]"b"$[1]Tranche avec
"d"$[3]pas 2
$[5:1:-2]"f"$[5]Tranche avec
"d"$[3]pas négatif
$[::-1]"g"$[6]Tranche en
"f"$[5]ordre inverse
"e"$[4]
"d"$[3]
"c"$[2]
"b"$[1]
"a"$[0]

Tableau 9 : Exemples de sélecteur de tranche de tableau

2.3.5. Filter Selector (Sélecteur de filtre)

Les sélecteurs de filtre servent à itérer sur les éléments ou membres de valeurs structurées, c'est-à-dire des tableaux et objets JSON. Les valeurs structurées sont identifiées dans la nodelist fournie par le segment enfant ou descendant au moyen du sélecteur de filtre.

Pour chaque itération (élément/membre), une expression logique (l'expression de filtre, filter expression) est évaluée, ce qui décide si le nœud de l'élément/membre est sélectionné. (Bien qu'une expression logique s'évalue en ce qui est mathématiquement une valeur booléenne, cette spécification utilise le terme logique pour maintenir une distinction avec les valeurs booléennes que JSON peut représenter.)

Durant l'itération, l'expression de filtre reçoit le nœud de chaque élément de tableau ou valeur de membre d'objet de la valeur structurée filtrée ; cet élément ou cette valeur de membre est alors connu comme le nœud courant (current node).

Le nœud courant peut servir de départ à une ou plusieurs requêtes JSONPath dans des sous-expressions de l'expression de filtre, notées via l'identifiant de nœud courant @. Chaque requête JSONPath peut servir soit à tester l'existence d'un résultat de la requête, soit à obtenir une valeur JSON spécifique issue de cette requête utilisable ensuite dans une comparaison, soit comme argument de fonction (function argument).

Les sélecteurs de filtre peuvent utiliser des extensions de fonctions, traitées à la section 2.4. Dans l'expression logique d'un sélecteur de filtre, des expressions de fonction peuvent opérer sur des nodelists et des valeurs. L'ensemble des fonctions disponibles est extensible, avec un certain nombre de fonctions prédéfinies (voir la section 2.4) et la possibilité d'enregistrer d'autres fonctions via le sous-registre « Function Extensions » (section 3.2). Lorsqu'une fonction est définie, on lui donne un nom unique, et sa valeur de retour ainsi que chacun de ses paramètres reçoivent un type déclaré (declared type). Le système de types est d'étendue limitée ; son rôle est d'exprimer des restrictions qui, sans fonctions, sont implicites dans la grammaire des expressions de filtre. Le système de types guide aussi les conversions (section 2.4.2) qui imitent la manière dont différents types d'expressions sont traités dans la grammaire lorsque les expressions de fonction ne sont pas utilisées.

2.3.5.1. Syntax (Syntaxe)

Le sélecteur de filtre a la forme ?<logical-expr>.

filter-selector     = "?" S logical-expr

Comme l'expression de filtre est composée d'éléments sans effets de bord, l'ordre d'évaluation n'a pas besoin d'être (et n'est pas) défini. De même, pour la conjonction (&&) et la disjonction (||) (définies plus loin), une implémentation à court-circuit et une évaluation complète mènent au même résultat ; les deux stratégies d'implémentation sont donc valides.

Le nœud courant est accessible via l'identifiant de nœud courant @. Cet identifiant désigne le nœud courant du sélecteur de filtre qui entoure directement l'identifiant. Note : Dans des sélecteurs de filtre imbriqués, il n'existe pas de syntaxe pour désigner le nœud courant d'autre chose que le sélecteur de filtre directement entourant l'identifiant (c'est-à-dire des sélecteurs de filtre entourant le sélecteur de filtre qui entoure directement l'identifiant).

Les expressions logiques offrent les opérateurs booléens habituels (|| pour OU, && pour ET, et ! pour NON). Ils ont la sémantique habituelle de l'algèbre de Boole et obéissent à ses lois (par exemple, voir [BOOLEAN-LAWS]). Des parenthèses PEUVENT être utilisées dans logical-expr pour le regroupement.

Il n'est pas exigé que logical-expr consiste en une expression entre parenthèses (ce qui était exigé dans [JSONPath-orig]), bien que ce soit possible, et la sémantique est la même sans parenthèses.

logical-expr        = logical-or-expr
logical-or-expr = logical-and-expr *(S "||" S logical-and-expr)
logical-and-expr = basic-expr *(S "&&" S basic-expr)
basic-expr          = paren-expr /
comparison-expr /
test-expr
paren-expr          = [logical-not-op S] "(" S logical-expr S ")"
logical-not-op = "!"

Une expression de test teste soit l'existence d'un nœud désigné par une requête embarquée (voir la section 2.3.5.2.1), soit le résultat d'une expression de fonction (voir la section 2.4). Dans ce dernier cas, si le type de résultat déclaré de la fonction est LogicalType (voir la section 2.4.1), on teste si le résultat est LogicalTrue ; si le type de résultat déclaré est NodesType, on teste si le résultat est non vide. Si le type de résultat déclaré est ValueType, son utilisation dans une expression de test n'est pas bien typée (voir la section 2.4.3).

test-expr           = [logical-not-op S]
(filter-query /
function-expr)
filter-query = rel-query / jsonpath-query
rel-query = current-node-identifier segments
current-node-identifier = "@"

Les expressions de comparaison permettent de comparer des valeurs primitives (c'est-à-dire nombres, chaînes, true, false et null). Elles peuvent provenir de littéraux ; de requêtes singulières, chacune sélectionnant au plus un nœud dont la valeur est alors utilisée ; ou d'expressions de fonction (voir la section 2.4) de type ValueType.

comparison-expr     = comparable S comparison-op S comparable
literal = number / string-literal /
true / false / null
comparable = literal /
singular-query /
function-expr
comparison-op = "==" / "!=" /
"<=" / ">=" /
"<" / ">"
singular-query      = rel-singular-query / abs-singular-query
rel-singular-query = current-node-identifier singular-query-segments
abs-singular-query = root-identifier singular-query-segments
singular-query-segments = *(S (name-segment / index-segment))
name-segment = ("[" name-selector "]") /
("." member-name-shorthand)
index-segment = "[" index-selector "]"

Les littéraux peuvent être notés comme d'habitude pour JSON (avec l'extension que les chaînes peuvent utiliser des délimiteurs simples quote).

Note : Les caractères alphabétiques dans les chaînes entre guillemets sont insensibles à la casse en ABNF, donc dans un nombre à virgule flottante, l'expression ABNF « e » peut être le caractère 'e' ou 'E'.

true, false et null sont en minuscules uniquement (sensibles à la casse).

number              = (int / "-0") [ frac ] [ exp ]
frac = "." 1*DIGIT
exp = "e" [ "-" / "+" ] 1*DIGIT
true = %x74.72.75.65
false = %x66.61.6c.73.65
null = %x6e.75.6c.6c

Le tableau 10 liste les opérateurs d'expression de filtre par ordre de priorité, de la plus forte (liaison la plus étroite) à la plus faible.

PrioritéType d'opérateurSyntaxe
5Regroupement(...)
Expressions de fonctionname(...)
4NON logique!
3Relations== !=
< <= > >=
2ET logique&&
1OU logique||

Tableau 10 : Priorité des opérateurs d'expression de filtre

2.3.5.2. Semantics (Sémantique)

Le sélecteur de filtre travaille exclusivement avec des tableaux et des objets. Son résultat est une liste de (zéro, un, plusieurs ou tous) leurs éléments de tableau ou valeurs de membre, respectivement. Appliqué à une valeur primitive, il ne sélectionne rien (et ne contribue donc pas au résultat du sélecteur de filtre).

Dans la nodelist résultante, les enfants d'un tableau sont ordonnés par leur position dans le tableau. L'ordre dans lequel les enfants d'un objet (par opposition à un tableau) apparaissent dans la nodelist résultante n'est pas prescrit, car les objets JSON sont non ordonnés.

2.3.5.2.1. Existence Tests (Tests d'existence)

Une requête seule dans un contexte logique est un test d'existence qui vaut true si la requête sélectionne au moins un nœud et false si la requête ne sélectionne aucun nœud.

Les tests d'existence diffèrent des comparaisons en ce qu' :

  • Ils fonctionnent avec des requêtes relatives ou absolues arbitraires (pas seulement des requêtes singulières).

  • Ils fonctionnent avec des requêtes qui sélectionnent des valeurs structurées.

Pour examiner la valeur d'un nœud sélectionné par une requête, une comparaison explicite est nécessaire. Par exemple, pour tester si le nœud sélectionné par @.foo a la valeur null, utiliser @.foo == null (voir la section 2.6) plutôt que le test d'existence négatif [email protected] (qui vaut false si @.foo sélectionne un nœud, quelle que soit la valeur du nœud). De même, @.foo == false ne vaut true que si @.foo sélectionne un nœud et que la valeur de ce nœud est false.

2.3.5.2.2. Comparisons (Comparaisons)

Les opérateurs de comparaison == et < sont définis d'abord, puis ils servent à définir !=, <=, >, et >=.

Lorsque l'un ou l'autre côté d'une comparaison aboutit à une nodelist vide ou au résultat spécial Nothing (voir la section 2.4.1) :

  • Une comparaison avec l'opérateur == vaut true si et seulement si l'autre côté aboutit aussi à une nodelist vide ou au résultat spécial Nothing.

  • Une comparaison avec l'opérateur < vaut false.

Lorsqu'une requête ou expression de fonction de l'un ou l'autre côté d'une comparaison aboutit à une nodelist constituée d'un seul nœud, ce côté est remplacé par la valeur de son nœud et alors :

  • Une comparaison avec l'opérateur == vaut true si et seulement si la comparaison porte sur :

    • des nombres censés interopérer, selon la section 2.2 d'I-JSON [RFC7493], qui sont égaux au sens de l'égalité mathématique usuelle,

    • des nombres dont au moins un n'est pas censé interopérer selon I-JSON, où les nombres sont égaux au sens d'une égalité propre à l'implémentation,

    • des valeurs primitives égales qui ne sont pas des nombres,

    • des tableaux égaux, c'est-à-dire des tableaux de même longueur où chaque élément du premier tableau est égal à l'élément correspondant du second tableau, ou

    • des objets égaux sans noms dupliqués, c'est-à-dire où :

      • les deux objets ont la même collection de noms (sans duplicatas) et

      • pour chacun de ces noms, les valeurs associées au nom par les objets sont égales.

  • Une comparaison avec l'opérateur < vaut true si et seulement si la comparaison porte sur des valeurs qui sont toutes deux des nombres ou toutes deux des chaînes et satisfont la comparaison :

    • les nombres censés interopérer, selon la section 2.2 d'I-JSON [RFC7493], DOIVENT être comparés selon l'ordre mathématique usuel ; les nombres non censés interopérer selon I-JSON PEUVENT être comparés selon un ordre propre à l'implémentation,

    • la chaîne vide est inférieure à toute chaîne non vide, et

    • une chaîne non vide est inférieure à une autre chaîne non vide si et seulement si la première chaîne commence par une valeur scalaire Unicode inférieure à celle de la seconde ou si les deux chaînes commencent par la même valeur scalaire Unicode et le reste de la première chaîne est inférieur au reste de la seconde.

!=, <=, >, et >= sont définis à partir des autres opérateurs de comparaison. Pour tout a et b :

  • La comparaison a != b vaut true si et seulement si a == b vaut false.

  • La comparaison a <= b vaut true si et seulement si a < b vaut true ou a == b vaut true.

  • La comparaison a > b vaut true si et seulement si b < a vaut true.

  • La comparaison a >= b vaut true si et seulement si b < a vaut true ou a == b vaut true.

2.3.5.3. Examples (Exemples)

Le premier ensemble d'exemples montre des expressions de comparaison et leur résultat pour une valeur JSON donnée en entrée.

JSON :

{
"obj": {"x": "y"},
"arr": [2, 3]
}

Comparaisons :

ComparaisonRésultatCommentaire
$.absent1 == $.absent2trueNodelists vides
$.absent1 <= $.absent2true== implique <=
$.absent == 'g'falseNodelist vide
$.absent1 != $.absent2falseNodelists vides
$.absent != 'g'trueNodelist vide
1 <= 2trueComparaison numérique
1 > 2falseComparaison numérique
13 == '13'falseIncompatibilité de type
'a' <= 'b'trueComparaison de chaînes
'a' > 'b'falseComparaison de chaînes
$.obj == $.arrfalseIncompatibilité de type
$.obj != $.arrtrueIncompatibilité de type
$.obj == $.objtrueComparaison d'objets
$.obj != $.objfalseComparaison d'objets
$.arr == $.arrtrueComparaison de tableaux
$.arr != $.arrfalseComparaison de tableaux
$.obj == 17falseIncompatibilité de type
$.obj != 17trueIncompatibilité de type
$.obj <= $.arrfalseObjets et tableaux :
pas de comparaison <
$.obj < $.arrfalseObjets et tableaux :
pas de comparaison <
$.obj <= $.objtrue== implique <=
$.arr <= $.arrtrue== implique <=
1 <= $.arrfalseTableaux : pas de <
1 >= $.arrfalseTableaux : pas de <
1 > $.arrfalseTableaux : pas de <
1 < $.arrfalseTableaux : pas de <
true <= truetrue== implique <=
true > truefalseBooléens : pas de <

Tableau 11 : Exemples de comparaisons

Le second ensemble d'exemples montre des requêtes JSONPath complètes utilisant des sélecteurs de filtre et les résultats de leur évaluation sur une valeur JSON donnée en entrée. (Note : Deux des requêtes emploient des extensions de fonctions ; voir les sections 2.4.6 et 2.4.7 pour les détails.)

JSON :

{
"a": [3, 5, 1, 2, 4, 6,
{"b": "j"},
{"b": "k"},
{"b": {}},
{"b": "kilo"}
],
"o": {"p": 1, "q": 2, "r": 3, "s": 5, "t": {"u": 6}},
"e": "f"
}

Requêtes :

Les exemples du tableau 12 montrent le sélecteur de filtre utilisé par un segment enfant.

RequêteRésultatChemins de résultatCommentaire
$.a[[email protected] =={"b":$['a'][9]Comparaison de
'kilo']"kilo"}valeur de membre
$.a[?(@.b =={"b":$['a'][9]Requête équivalente
'kilo')]"kilo"}avec parenthèses
$.a[?@>3.5]5$['a'][1]Comparaison de
4$['a'][4]valeurs de tableau
6$['a'][5]
$.a[[email protected]]{"b": "j"}$['a'][6]Existence sur
{"b": "k"}$['a'][7]valeurs de tableau
{"b": {}}$['a'][8]
{"b":$['a'][9]
"kilo"}
$[?@.*][3, 5, 1,$['a']Existence de
2, 4, 6,$['o']requêtes non singulières
{"b": "j"},
{"b": "k"},
{"b": {}},
{"b":
"kilo"}]
{"p": 1,
"q": 2,
"r": 3,
"s": 5,
"t": {"u":
6}}
$[?@[[email protected]]][3, 5, 1,$['a']Filtres imbriqués
2, 4, 6,
{"b": "j"},
{"b": "k"},
{"b": {}},
{"b":
"kilo"}]
$.o[?@<3, ?@<3]1$['o']['p']Ordre non déterministe
2$['o']['q']
2$['o']['q']
1$['o']['p']
$.a[?@<2 || @.b1$['a'][2]OU logique sur
== "k"]{"b": "k"}$['a'][7]valeurs de tableau
$.a[?match(@.b,{"b": "j"}$['a'][6]Correspondance
"[jk]")]{"b": "k"}$['a'][7]d'expression régulière
$.a[?search(@.b,{"b": "j"}$['a'][6]Recherche
"[jk]")]{"b": "k"}$['a'][7]d'expression régulière
{"b":$['a'][9]
"kilo"}
$.o[?@>1 && @<4]2$['o']['q']ET logique sur
3$['o']['r']valeurs d'objet
$.o[?@>1 && @<4]3$['o']['r']Résultat
2$['o']['q']alternatif
$.o[[email protected] || @.x]{"u": 6}$['o']['t']OU logique sur
valeurs d'objet
$.a[[email protected] == $.x]3$['a'][0]Comparaison de
5$['a'][1]requêtes sans
1$['a'][2]valeurs
2$['a'][3]
4$['a'][4]
6$['a'][5]
$.a[?@ == @]3$['a'][0]Comparaisons de
5$['a'][1]valeurs primitives
1$['a'][2]et structurées
2$['a'][3]
4$['a'][4]
6$['a'][5]
{"b": "j"}$['a'][6]
{"b": "k"}$['a'][7]
{"b": {}}$['a'][8]
{"b":$['a'][9]
"kilo"}

Tableau 12 : Exemples de sélecteur de filtre

L'exemple ci-dessus avec la requête $.o[?@<3, ?@<3] montre qu'un sélecteur de filtre peut produire des nodelists dans des ordres distincts à chaque fois qu'il apparaît dans le segment enfant.