Documentation PostgreSQL 14.22 » Langage SQL » Fonctions et opérateurs » Fonctions et opérateurs JSON

Précédent | Niveau supérieur | Suivant
9.15. Fonctions XML | Sommaire | 9.17. Fonctions de manipulation de séquence

## 9.16. Fonctions et opérateurs JSON

Cette section décrit :

- les fonctions et opérateurs pour traiter et créer des données JSON

- le langage de chemin SQL/JSON

Pour en savoir plus sur le standard SQL/JSON, voir [sqltr-19075-6]. Pour des détails sur les types JSON supportés dans PostgreSQL, voir Section 8.14.

### 9.16.1. Traiter et créer des données JSON

Tableau 9.44 affiche les opérateurs disponibles pour les types de données JSON (voir Section 8.14). De plus, les opérateurs de comparaison habituels indiqués dans Tableau 9.1 sont disponibles pour le type `jsonb`, mais pas pour le type `json`. Les opérateurs de comparaison suivent les règles de tri des opérateurs B-tree indiqués dans Section 8.14.4. Voir aussi Section 9.21 pour la fonction d'agrégat `json_agg` qui agrège les valeurs d'enregistrements sous la forme d'un JSON, pour la fonction d'agrégat `json_object_agg` qui agrège des paires de valeurs dans un objet JSON, et leurs équivalents `jsonb`, à savoir `jsonb_agg` et `jsonb_object_agg`.

Tableau 9.44. Opérateurs `json` et `jsonb`

Opérateur Description Exemple(s)
`json` `->` `integer` → `json` `jsonb` `->` `integer` → `jsonb` Extrait le `n`-ième élément d'un tableau JSON (les éléments du tableau sont indexés à partir de zéro, mais les nombres négatifs sont pris en compte à partir de la fin). `'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> 2` → `{"c":"baz"}` `'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> -3` → `{"a":"foo"}`
`json` `->` `text` → `json` `jsonb` `->` `text` → `jsonb` Extrait le champ objet JSON avec la clé donnée. `'{"a": {"b":"foo"}}'::json -> 'a'` → `{"b":"foo"}`
`json` `->>` `integer` → `text` `jsonb` `->>` `integer` → `text` Extrait le `n`-ième élément d'un tableau JSON, comme le `text`. `'[1,2,3]'::json ->> 2` → `3`
`json` `->>` `text` → `text` `jsonb` `->>` `text` → `text` Extrait le champ objet JSON d'après la clé donnée, comme `text`. `'{"a":1,"b":2}'::json ->> 'b'` → `2`
`json` `#>` `text[]` → `json` `jsonb` `#>` `text[]` → `jsonb` Extrait le sous-objet JSON d'un chemin spécifié, où les éléments du chemin peuvent être soit les clés d'un champ, soit les indices d'un tableau. `'{"a": {"b": ["foo","bar"]}}'::json #> '{a,b,1}'` → `"bar"`
`json` `#>>` `text[]` → `text` `jsonb` `#>>` `text[]` → `text` Extrait le sous-objet JSON au chemin spécifié avec `text`. `'{"a": {"b": ["foo","bar"]}}'::json #>> '{a,b,1}'` → `bar`

### Note

Les opérateurs d'extraction champ/élément/chemin renvoient NULL, plutôt qu'une erreur, si l'entrée JSON n'a pas la bonne structure correspondant à la requête ; par exemple si la clé ou l'élément du tableau n'existe pas.

Quelques opérateurs supplémentaires existent seulement pour le type `jsonb`, comme indiqué dans Tableau 9.45. Section 8.14.4 décrit comment ces opérateurs peuvent être utilisés pour rechercher efficacement les données `jsonb` indexées.

Tableau 9.45. Opérateurs `jsonb` supplémentaires

Opérateur Description Exemple(s)
`jsonb` `@>` `jsonb` → `boolean` Est-ce que la première valeur JSON contient la seconde ? (Voir Section 8.14.3 pour les détails sur la notion de contenu.) `'{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb` → `t`
`jsonb` `<@` `jsonb` → `boolean` Est-ce que la première valeur JSON est contenue dans la seconde ? `'{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb` → `t`
`jsonb` `?` `text` → `boolean` Est-ce que la chaîne de caractères existe comme clé de haut niveau ou élément de tableau dans la valeur JSON ? `'{"a":1, "b":2}'::jsonb ? 'b'` → `t` `'["a", "b", "c"]'::jsonb ? 'b'` → `t`
`jsonb` `?|` `text[]` → `boolean` Est-ce qu'une des chaînes du tableau de texte existe comme clé de haut niveau ou comme élément de tableau ? `'{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'd']` → `t`
`jsonb` `?&` `text[]` → `boolean` Est-ce que toutes les chaînes du tableau de texte existent comme clés de haut niveau ou comme éléments de tableau ? `'["a", "b", "c"]'::jsonb ?& array['a', 'b']` → `t`
`jsonb` `||` `jsonb` → `jsonb` Concatène deux valeurs `jsonb`. Concaténer deux tableaux génère un tableau contenant tous les éléments de chaque entrée. Concaténer deux objets génère un objet contenant l'union de leurs clés, en prenant la valeur du deuxième objet quand il existe deux clés dupliquées. Tous les autres cas sont traités en convertissant une entrée non tableau en un tableau à un seul élément, puis en le traitant comme pour deux tableaux. N'est pas récursif : seul le tableau ou la structure objet de haut niveau est assemblé. `'["a", "b"]'::jsonb || '["a", "d"]'::jsonb` → `["a", "b", "a", "d"]` `'{"a": "b"}'::jsonb || '{"c": "d"}'::jsonb` → `{"a": "b", "c": "d"}` `'[1, 2]'::jsonb || '3'::jsonb` → `[1, 2, 3]` `'{"a": "b"}'::jsonb || '42'::jsonb` → `[{"a": "b"}, 42]` Pour concaténer un tableau à un autre tableau dans une entrée unique, il faut l'envelopper dans une couche supplémentaire de tableau, par exemple : `'[1, 2]'::jsonb || jsonb_build_array('[3, 4]'::jsonb)` → `[1, 2, [3, 4]]`
`jsonb` `-` `text` → `jsonb` Supprime une clé (et sa valeur) à partir d'un objet JSON, ou les valeurs correspondantes de chaînes à partir d'un tableau JSON. `'{"a": "b", "c": "d"}'::jsonb - 'a'` → `{"c": "d"}` `'["a", "b", "c", "b"]'::jsonb - 'b'` → `["a", "c"]`
`jsonb` `-` `text[]` → `jsonb` Supprime toutes les clés ou tous les éléments de tableau correspondant à partir de l'opérande gauche. `'{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]` → `{}`
`jsonb` `-` `integer` → `jsonb` Supprime l'élément de tableau pour l'index spécifié (les nombres négatifs se décomptent à partir de la fin). Renvoie une erreur si la valeur JSON n'est pas un tableau. `'["a", "b"]'::jsonb - 1` → `["a"]`
`jsonb` `#-` `text[]` → `jsonb` Supprime le champ ou l'élément de tableau sur le chemin indiqué, les éléments du chemin pouvant être soit des clés de champ, soit des indices de tableau. `'["a", {"b":1}]'::jsonb #- '{1,b}'` → `["a", {}]`
`jsonb` `@?` `jsonpath` → `boolean` Est-ce que le chemin JSON renvoie tout élément pour la valeur JSON spécifiée ? `'{"a":[1,2,3,4,5]}'::jsonb @? '$.a[*] ? (@ > 2)'` → `t`
`jsonb` `@@` `jsonpath` → `boolean` Renvoie le résultat d'une vérification de prédicat du chemin JSON pour la valeur JSON indiquée. Seul le premier élément du résultat est pris en compte. Si le résultat n'est pas un booléen, alors `NULL` est renvoyé. `'{"a":[1,2,3,4,5]}'::jsonb @@ '$.a[*] > 2'` → `t`

### Note

Les opérateurs `@?` et `@@` du type `jsonpath` suppriment les erreurs suivantes : champ objet ou élément de tableau manquant, type d'élément JSON inattendu, erreurs de date/heure ou de numérique. Les fonctions relatives à `jsonpath` décrites ci-dessous peuvent aussi supprimer ce type d'erreurs à la demande. Ce comportement pourrait être utile lors de la recherche de collections de documents JSON de différentes structures.

Tableau 9.46 montre les fonctions disponibles pour construire des valeurs `json` et `jsonb`.

Tableau 9.46. Fonctions de création de JSON

Fonction Description Exemple(s)
`to_json` ( `anyelement` ) → `json` `to_jsonb` ( `anyelement` ) → `jsonb` Convertit toute valeur SQL en `json` ou `jsonb`. Les tableaux et valeurs composites sont convertis récursivement en tableaux et en objets (les tableaux multidimensionnels deviennent des tableaux de tableaux en JSON). Sinon, s'il existe une conversion entre le type de données SQL et `json`, la fonction de conversion sera utilisée pour réaliser la conversion ;[a] sinon, une valeur JSON scalaire est produite. Pour tout scalaire autre qu'un nombre, un booléen ou une valeur NULL, la représentation textuelle sera utilisée avec les échappements nécessaires pour la transformer en valeur JSON valide. `to_json('Fred said "Hi."'::text)` → `"Fred said \"Hi.\""` `to_jsonb(row(42, 'Fred said "Hi."'::text))` → `{"f1": 42, "f2": "Fred said \"Hi.\""}`
`array_to_json` ( `anyarray` [, `boolean` ] ) → `json` Convertit un tableau SQL en tableau JSON. Le comportement est le même que `to_json` sauf que des sauts de ligne seront ajoutés entre les éléments de tableau de haut niveau si le paramètre booléen optionnel vaut true. `array_to_json('{{1,5},{99,100}}'::int[])` → `[[1,5],[99,100]]`
`row_to_json` ( `record` [, `boolean` ] ) → `json` Convertit une valeur composite SQL en objet JSON. Le comportement est le même que `to_json` sauf que des sauts de ligne seront ajoutés entre les éléments de tableau de haut niveau si le paramètre booléen optionnel vaut true. `row_to_json(row(1,'foo'))` → `{"f1":1,"f2":"foo"}`
`json_build_array` ( `VARIADIC` `"any"` ) → `json` `jsonb_build_array` ( `VARIADIC` `"any"` ) → `jsonb` Construit un tableau JSON avec des types potentiellement hétérogènes à partir d'une liste d'arguments de longueur variable. Chaque argument est converti avec la fonction `to_json` ou `to_jsonb`. `json_build_array(1, 2, 'foo',4,5)` → `[1, 2, "foo", 4, 5]`
`json_build_object` ( `VARIADIC` `"any"` ) → `json` `jsonb_build_object` ( `VARIADIC` `"any"` ) → `jsonb` Construit un objet JSON à partir d'une liste d'arguments de longueur indéfinie. Par convention, la liste d'arguments consiste en des clés et valeurs en alternance. Les arguments clés sont convertis en texte ; les arguments valeurs sont convertis via les fonctions `to_json` ou `to_jsonb`. `json_build_object('foo', 1, 2, row(3, 'bar'))` → `{"foo" : 1, "2" : {"f1":3,"f2":"bar"}}`
`json_object` ( `text[]` ) → `json` `jsonb_object` ( `text[]` ) → `jsonb` Construit un objet JSON à partir d'un tableau de texte. Le tableau doit avoir soit exactement une dimension avec un nombre pair de membres, auquel cas ils sont pris comme des paires alternantes clé/valeur, ou deux dimensions de telle façon que le tableau interne a exactement deux éléments, pris comme une paire clé/valeur. Toutes les valeurs sont converties en chaîne JSON. `json_object('{a, 1, b, "def", c, 3.5}')` → `{"a" : "1", "b" : "def", "c" : "3.5"}` `json_object('{{a, 1}, {b, "def"}, {c, 3.5}}')` → `{"a" : "1", "b" : "def", "c" : "3.5"}`
`json_object` ( `keys` `text[]`, `values` `text[]` ) → `json` `jsonb_object` ( `keys` `text[]`, `values` `text[]` ) → `jsonb` Cette forme de `json_object` prend les clés et valeurs à partir de tableaux de texte séparés. Pour le reste, elle est identique à la forme à un argument. `json_object('{a, b}', '{1,2}')` → `{"a": "1", "b": "2"}`
[a] Par exemple, l'extension hstore contient une conversion de `hstore` vers `json`, pour que les valeurs `hstore` converties par les fonctions de création JSON soient représentées en tant qu'objets JSON, et non pas comme des valeurs de type chaîne de caractères.

Tableau 9.47 montre les fonctions disponibles pour le traitement de valeurs `json` et `jsonb`.

Tableau 9.47. Fonctions de traitement JSON

Fonction Description Exemple(s)
`json_array_elements` ( `json` ) → `setof json` `jsonb_array_elements` ( `jsonb` ) → `setof jsonb` Étend le tableau JSON de haut niveau en un ensemble de valeurs JSON. `select * from json_array_elements('[1,true, [2,false]]')` → ``
       value
    -----------
     1
     true
     [2,false]
`json_array_elements_text` ( `json` ) → `setof text` `jsonb_array_elements_text` ( `jsonb` ) → `setof text` Étend le tableau JSON de haut niveau en un ensemble de valeurs de type `text`. `select * from json_array_elements_text('["foo", "bar"]')` → ``
       value
    -----------
     foo
     bar
`json_array_length` ( `json` ) → `integer` `jsonb_array_length` ( `jsonb` ) → `integer` Renvoie le nombre d'éléments dans le tableau JSON de haut niveau. `json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]')` → `5` `jsonb_array_length('[]')` → `0`
`json_each` ( `json` ) → `setof record` ( `key` `text`, `value` `json` ) `jsonb_each` ( `jsonb` ) → `setof record` ( `key` `text`, `value` `jsonb` ) Étend l'objet JSON de haut niveau en un ensemble de paires clé/valeur. `select * from json_each('{"a":"foo", "b":"bar"}')` → ``
     key | value
    -----+-------
     a   | "foo"
     b   | "bar"
`json_each_text` ( `json` ) → `setof record` ( `key` `text`, `value` `text` ) `jsonb_each_text` ( `jsonb` ) → `setof record` ( `key` `text`, `value` `text` ) Étend l'objet JSON de haut niveau en un ensemble de paires clé/valeur. Les `value` renvoyées seront de type `text`. `select * from json_each_text('{"a":"foo", "b":"bar"}')` → ``
     key | value
    -----+-------
     a   | foo
     b   | bar
`json_extract_path` ( `from_json` `json`, `VARIADIC` `path_elems` `text[]` ) → `json` `jsonb_extract_path` ( `from_json` `jsonb`, `VARIADIC` `path_elems` `text[]` ) → `jsonb` Extrait un sous-objet JSON au chemin spécifié. (Ceci est fonctionnellement équivalent à l'opérateur `#>`, mais écrire le chemin sous la forme d'une liste peut être plus agréable dans certains cas.) `json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')` → `"foo"`
`json_extract_path_text` ( `from_json` `json`, `VARIADIC` `path_elems` `text[]` ) → `text` `jsonb_extract_path_text` ( `from_json` `jsonb`, `VARIADIC` `path_elems` `text[]` ) → `text` Extrait le sous-objet JSON au chemin spécifié sous la forme d'un `text`. (Ceci est équivalent fonctionnement à l'opérateur `#>>`.) `json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')` → `foo`
`json_object_keys` ( `json` ) → `setof text` `jsonb_object_keys` ( `jsonb` ) → `setof text` Renvoie l'ensemble de clés dans l'objet JSON de haut niveau. `select * from json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}')` → ``
     json_object_keys
    ------------------
     f1
     f2
`json_populate_record` ( `base` `anyelement`, `from_json` `json` ) → `anyelement` `jsonb_populate_record` ( `base` `anyelement`, `from_json` `jsonb` ) → `anyelement` Étend l'objet JSON de haut niveau en une ligne ayant le type composite de l'argument `base`. L'objet JSON est parcouru pour y trouver les champs dont le nom correspond aux noms de colonnes du type de la ligne en sortie, et leurs valeurs sont insérées dans ces colonnes en sortie. (Les champs qui ne correspondent à aucun nom de colonne en sortie sont ignorés.) Dans le cas d'une utilisation typique, la valeur de `base` est simplement `NULL`, ce qui signifie que toute colonne en sortie qui ne correspond pas à un champ d'objet sera remplie avec un NULL. Néanmoins, si `base` ne vaut pas `NULL`, alors les valeurs qu'il contient seront utilisées pour les colonnes sans correspondance. Pour convertir une valeur JSON au type SQL d'une colonne en sortie, les règles suivantes sont appliquées sur cette séquence : Une valeur JSON null est convertie en NULL SQL dans tous les cas. Si la colonne en sortie est de type `json` ou `jsonb`, la valeur JSON est reproduite exactement. Si la colonne en sortie est un type (de ligne) composite, et que la valeur JSON est un objet JSON, les champs de l'objet sont convertis en colonnes du type de ligne par application récursive de ces règles. De la même façon, si la colonne en sortie est un type tableau et que la valeur JSON est un tableau JSON, les éléments du tableau JSON sont convertis en éléments du tableau en sortie par application récursive de ces règles. Sinon, si la valeur JSON est une chaîne, le contenu de la chaîne est donné à la fonction de conversion en entrée pour le type de données de la colonne. Sinon, la représentation textuelle habituelle de la valeur JSON est envoyée à la fonction de conversion en entrée pour le type de données de la colonne. Bien que l'exemple ci-dessous utilise une valeur constante JSON, une utilisation typique serait de référencer une colonne `json` ou `jsonb` latéralement d'une autre table dans la clause `FROM` de la requête. Écrire `json_populate_record` dans la clause `FROM` est une bonne pratique, car toutes les colonnes extraites sont utilisables sans avoir à faire des appels dupliqués à la fonction. `create type subrowtype as (d int, e text);` `create type myrowtype as (a int, b text[], c subrowtype);` `select * from json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}, "x": "foo"}')` → ``
     a |   b       |      c
    ---+-----------+-------------
     1 | {2,"a b"} | (4,"a b c")
`json_populate_recordset` ( `base` `anyelement`, `from_json` `json` ) → `setof anyelement` `jsonb_populate_recordset` ( `base` `anyelement`, `from_json` `jsonb` ) → `setof anyelement` Étend le tableau JSON de haut niveau composé d'objets en un ensemble de lignes ayant le type composite de l'argument `base`. Chaque élément du tableau JSON est traité comme décrit ci-dessus pour `json[b]_populate_record`. `create type twoints as (a int, b int);` `select * from json_populate_recordset(null::twoints, '[{"a":1,"b":2}, {"a":3,"b":4}]')` → ``
     a | b
    ---+---
     1 | 2
     3 | 4
`json_to_record` ( `json` ) → `record` `jsonb_to_record` ( `jsonb` ) → `record` Étend l'objet JSON de haut niveau en une ligne ayant le type composite défini par une clause `AS`. (Comme avec toutes les fonctions renvoyant `record`, la requête appelante doit explicitement définir la structure de l'enregistrement avec une clause `AS`.) L'enregistrement en sortie est rempli avec les champs de l'objet JSON, de la même façon que décrite ci-dessus pour `json[b]_populate_record`. Comme il n'existe aucune valeur record en entrée, les colonnes sans correspondance sont remplies avec des NULL. `create type myrowtype as (a int, b text);` `select * from json_to_record('{"a":1, "b":[1,2,3], "c":[1,2,3], "e":"bar", "r": {"a": 123, "b": "a b c"}}') as x(a int, b text, c int[], d text, r myrowtype)` → ``
     a |    b    |    c    | d |       r
    ---+---------+---------+---+---------------
     1 | [1,2,3] | {1,2,3} |   | (123,"a b c")
`json_to_recordset` ( `json` ) → `setof record` `jsonb_to_recordset` ( `jsonb` ) → `setof record` Étend le tableau JSON de haut niveau composé d'objets en un ensemble de lignes ayant le type composite défini par une clause `AS`. (Comme avec toutes les fonctions renvoyant `record`, la requête appelante doit explicitement définir la structure de l'enregistrement avec une clause `AS`.) Chaque élément du tableau JSON est traité comme décrit ci-dessus pour `json[b]_populate_record`. `select * from json_to_recordset('[{"a":1,"b":"foo"}, {"a":"2","c":"bar"}]') as x(a int, b text)` → ``
     a |  b
    ---+-----
     1 | foo
     2 |
`jsonb_set` ( `target` `jsonb`, `path` `text[]`, `new_value` `jsonb` [, `create_if_missing` `boolean` ] ) → `jsonb` Renvoie `target` avec l'élément désigné par `path` remplacé par `new_value` ou avec `new_value` ajouté si `create_if_missing` vaut true (ce qui est la valeur par défaut) et si l'élément désigné par `path` n'existe pas. Toutes les étapes précédentes dans le chemin doivent exister, sinon le `target` est renvoyé intact. Comme avec les opérateurs orientés chemin, les entiers négatifs qui apparaissent dans `path` se décomptent à partir de la fin des tableaux JSON. Si l'étape du dernier chemin est un index inexistant (hors limite) du tableau et si `create_if_missing` vaut true, la nouvelle valeur est ajoutée au début du tableau si l'index est négatif et à la fin du tableau s'il est positif. `jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}','[2,3,4]', false)` → `[{"f1": [2, 3, 4], "f2": null}, 2, null, 3]` `jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}', '[2,3,4]')` → `[{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2]`
`jsonb_set_lax` ( `target` `jsonb`, `path` `text[]`, `new_value` `jsonb` [, `create_if_missing` `boolean` [, `null_value_treatment` `text` ]] ) → `jsonb` Si `new_value` n'est pas `NULL`, se comporte de façon identique à `jsonb_set`. Sinon se comporte suivant la valeur de `null_value_treatment` qui doit être parmi `'raise_exception'`, `'use_json_null'`, `'delete_key'` ou `'return_target'`. Par défaut, il s'agit de `'use_json_null'`. `jsonb_set_lax('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', null)` → `[{"f1": null, "f2": null}, 2, null, 3]` `jsonb_set_lax('[{"f1":99,"f2":null},2]', '{0,f3}', null, true, 'return_target')` → `[{"f1": 99, "f2": null}, 2]`
`jsonb_insert` ( `target` `jsonb`, `path` `text[]`, `new_value` `jsonb` [, `insert_after` `boolean` ] ) → `jsonb` Renvoie `target` avec `new_value` inséré. Si l'élément désigné par `path` est un élément de tableau, `new_value` sera inséré avant cet élément si `insert_after` vaut false (ce qui est la valeur par défaut) ou après si `insert_after` vaut true. Si l'élément désigné par `path` est un champ objet, `new_value` sera inséré seulement si l'objet ne contient pas déjà cette clé. Toutes les étapes précédentes dans le chemin doivent exister, sinon `target` est renvoyé non modifié. Comme avec les opérateurs orientés chemin, les nombres négatifs qui apparaissent dans `path` sont décomptés à partir de la fin des tableaux JSON. Si la dernière étape du chemin est un index hors limite de tableau, la nouvelle valeur est ajoutée au début du tableau si l'index est négatif ou à la fin du tableau s'il est positif. `jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"')` → `{"a": [0, "new_value", 1, 2]}` `jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true)` → `{"a": [0, 1, "new_value", 2]}`
`json_strip_nulls` ( `json` ) → `json` `jsonb_strip_nulls` ( `jsonb` ) → `jsonb` Supprime tous les champs objets ayant des valeurs NULL à partir de la valeur JSON donnée, de façon récurvise. Les valeurs NULL qui ne sont pas des champs objets ne sont pas touchées. `json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]')` → `[{"f1":1},2,null,3]`
`jsonb_path_exists` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `boolean` Vérifie si le chemin JSON renvoie des éléments de la valeur JSON spécifiée. Si l'argument `vars` est indiqué, il doit correspondre à un objet JSON, et ses champs fournissent des valeurs nommées à substituer dans l'expression `jsonpath`. Si l'argument `silent` est indiqué et vaut `true`, la fonction supprime les mêmes erreurs que les opérateurs `@?` et `@@`. `jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2,"max":4}')` → `t`
`jsonb_path_match` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `boolean` Renvoie le résultat de la vérification d'un prédicat de chemin JSON pour la valeur JSON spécifiée. Seul le premier élément du résultat est pris en compte. Si le résultat n'est pas un booléen, alors `NULL` est renvoyé. Les arguments optionnels `vars` et `silent` agissent de la même façon que pour `jsonb_path_exists`. `jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{"min":2,"max":4}')` → `t`
`jsonb_path_query` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `setof jsonb` Renvoie tous les éléments JSON renvoyés par le chemin JSON pour la valeur JSON spécifiée. Les arguments optionnels `vars` et `silent` agissent de la même façon que pour `jsonb_path_exists`. `select * from jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2,"max":4}')` → ``
     jsonb_path_query
    ------------------
     2
     3
     4
`jsonb_path_query_array` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `jsonb` Renvoie tous les éléments JSON renvoyés par le chemin JSON pour la valeur JSON spécifiée, sous la forme d'un tableau JSON. Les arguments optionnels `vars` et `silent` agissent de la même façon que pour `jsonb_path_exists`. `jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')` → `[2, 3, 4]`
`jsonb_path_query_first` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `jsonb` Renvoie le premier élément JSON renvoyé par le chemin JSON pour la valeur JSON spécifiée. Renvoie `NULL` s'il n'y a pas de résultat. Les arguments optionnels `vars` et `silent` agissent de la même façon que pour `jsonb_path_exists`. `jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')` → `2`
`jsonb_path_exists_tz` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `boolean` `jsonb_path_match_tz` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `boolean` `jsonb_path_query_tz` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `setof jsonb` `jsonb_path_query_array_tz` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `jsonb` `jsonb_path_query_first_tz` ( `target` `jsonb`, `path` `jsonpath` [, `vars` `jsonb` [, `silent` `boolean` ]] ) → `jsonb` Ces fonctions agissent comme leurs homologues décrits ci-dessus sans le suffixe `_tz`, sauf que ces fonctions acceptent la comparaison de valeurs date/heure qui nécessitent des conversions adaptées suivant le fuseau horaire. L'exemple ci-dessous requiert l'interprétation de la valeur date seule `2015-08-02` comme un horodatage avec fuseau horaire, pour que le résultat dépende du paramétrage actuel de TimeZone. Du fait de cette dépendance, ces fonctions sont marquées stables, ce qui signifie que ces fonctions ne peuvent pas être utilisées dans les index. Leurs homologues sont immuables, et donc peuvent être utilisés dans les index ; cependant, elles renverront des erreurs si on leur demande ce type de comparaison. `jsonb_path_exists_tz('["2015-08-01 12:00:00-05"]', '$[*] ? (@.datetime() < "2015-08-02".datetime())')` → `t`
`jsonb_pretty` ( `jsonb` ) → `text` Convertit la valeur JSON donnée en un texte proprement indenté. `jsonb_pretty('[{"f1":1, "f2":null}, 2]')` → ``
    [
        {
            "f1": 1,
            "f2": null
        },
        2
    ]
`json_typeof` ( `json` ) → `text` `jsonb_typeof` ( `jsonb` ) → `text` Renvoie le type de la valeur JSON de haut niveau sous la forme d'une chaîne de caractères. Les types possibles sont `object`, `array`, `string`, `number`, `boolean` et `null`. (Le résultat `null` ne doit pas être pris pour un NULL SQL ; voir les exemples.) `json_typeof('-123.4')` → `number` `json_typeof('null'::json)` → `null` `json_typeof(NULL::json) IS NULL` → `t`

### 9.16.2. Le langage de chemin SQL/JSON

Les expressions de chemin SQL/JSON indiquent les éléments à récupérer à partir de données JSON, similaires aux expressions XPath utilisées pour l'accès SQL au XML. Dans PostgreSQL, les expressions de chemin sont implémentées sous la forme du type de données `jsonpath` et peuvent utiliser tout élément décrit dans Section 8.14.7.

Les fonctions et opérateurs de requêtes JSON passent l'expression de chemin fournie au moteur de chemin pour évaluation. Si l'expression correspond à la donnée JSON requêtée, l'élément JSON correspondant ou l'ensemble d'éléments est renvoyé. Les expressions de chemin sont écrites dans le langage de chemin SQL/JSON et peuvent inclure les expressions et fonctions arithmétiques.

Une expression de chemin consiste en une séquence d'éléments autorisés par le type de données `jsonpath`. L'expression de chemin est habituellement évaluée de gauche à droite, mais vous pouvez utiliser les parenthèses pour modifier l'ordre des opérations. Si l'évaluation réussit, une séquence d'éléments JSON est produite et le résultat de l'évaluation est renvoyé à la fonction de requête JSON qui termine le traitement indiqué.

Pour faire référence à la valeur JSON en cours de requêtage (l'élément de contexte), utilisez la variable `$` dans l'expression de chemin. Elle peut être suivie par un ou plusieurs opérateurs d'accesseurs, qui descendent dans la structure JSON, étape par étape, pour récupérer les sous-éléments de l'élément de contexte. Chaque opérateur qui suit traite le résultat de l'étape d'évaluation précédente.

Par exemple, supposez que vous ayez certaines données JSON à partir d'un traqueur GPS que vous voulez analyser, tel que :

    {
      "track": {
        "segments": [
          {
            "location":   [ 47.763, 13.4034 ],
            "start time": "2018-10-14 10:05:14",
            "HR": 73
          },
          {
            "location":   [ 47.706, 13.2635 ],
            "start time": "2018-10-14 10:39:21",
            "HR": 135
          }
        ]
      }
    }

Pour récupérer les segments de piste disponibles, vous avez besoin d'utiliser l'opérateur d'accesseur `.`key`` pour descendre à travers les objets JSON tout autour :

    $.track.segments

Pour récupérer le contenu d'un tableau, vous utilisez typiquement l'opérateur `[*]`. Par exemple, le chemin suivant renverra les coordonnées d'emplacement pour tous les segments de piste disponibles :

    $.track.segments[*].location

Pour renvoyer les coordonnées du premier segment seulement, vous pouvez indiquer l'indice correspondant dans l'opérateur `[]`. Rappellez-vous que les indices de tableau JSON commencent à 0 :

    $.track.segments[0].location

Le résultat de chaque étape d'évaluation de chemin peut être traité par un ou plusieurs opérateurs et méthodes `jsonpath`, listés dans Section 9.16.2.2. Chaque nom de méthode doit être précédé d'un point. Par exemple, vous pouvez obtenir la taille d'un tableau :

    $.track.segments.size()

D'autres exemples d'utilisation d'opérateurs et méthodes `jsonpath` à l'intérieur d'expressions de chemins apparaissent ci-dessous dans Section 9.16.2.2.

Lors de la définition d'un chemin, vous pouvez aussi utiliser une ou plusieurs expressions de filtre qui fonctionnent de façon similaire à la clause `WHERE` en SQL. Une expression de filtre commence avec un point d'interrogation et fournit une condition entre parenthèses :

    ? (condition)

Les expressions de filtre doivent être écrites juste après l'étape d'évaluation du chemin auquel elles s'appliquent. Le résultat de cette étape est filtré pour inclure seulement les éléments qui satisfont la condition fournie. SQL/JSON définit une logique à trois valeurs, donc la condition peut valoir `true`, `false` ou `unknown`. La valeur `unknown` joue le même rôle que le `NULL` SQL et peut être testée avec le prédicat `is unknown`. Les étapes suivantes d'évaluation du chemin utilisent seulement les éléments pour lesquels l'expression de filtre renvoie `true`.

Les fonctions et opérateurs pouvant être utilisés dans des expressions de filtre sont listés dans Tableau 9.49. À l'intérieur d'une expression de filtre, la variable `@` dénote la valeur en cours de filtrage (un résultat de l'étape de chemin précédente). Vous pouvez écrire les opérateurs d'accesseurs après `@` pour récupérer les éléments du composant.

Par exemple, supposez que vous vouliez récupérer toutes les valeurs de fréquence cardiaque supérieures à 130. Vous pouvez le faire en utilisant l'expression suivante :

    $.track.segments[*].HR ? (@ > 130)

Pour obtenir les heures de début des segments ayant une telle valeur, vous devez filtrer les segments incompatiables avant de renvoyer les heures de début, donc l'expression de filtre est appliquée à l'étape précédente, et le chemin utilisé dans la condition est différent :

    $.track.segments[*] ? (@.HR > 130)."start time"

Vous pouvez utiliser plusieurs expressions de filtre en séquence, si nécessaire. Par exemple, l'expression suivante sélectionne les heures de début de tous les segments qui contiennent des emplacements avec les bonnes coordonnées et les valeurs hautes de fréquence cardiaque :

    $.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"

Il est aussi autorisé d'utiliser des expressions de filtre à différents niveaux de profondeur. L'exemple suivant filtre tout d'abord tous les segments par emplacement, puis renvoie les valeurs hautes de fréquence cardiaque sur ces segments, si disponibles :

    $.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)

Vous pouvez aussi imbriquer les expressions de filtre :

    $.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()

Cette expression renvoie la taille de la trace si elle contient des segments avec des valeurs hautes de fréquence cardiaque ou, sinon, une séquence vide.

L'implémentation PostgreSQL du langage de chemin SQL/JSON présente les différences suivantes sur le standard SQL/JSON :

- Une expression de chemin peut être un prédicat booléen, bien que le standard SQL/JSON autorise les prédicats uniquement dans les filtres. Ceci est nécessaire pour l'implémentation de l'opérateur `@@`. Par exemple, l'expression `jsonpath` suivante est valide dans PostgreSQL :

      $.track.segments[*].HR < 70

- Il existe des différences mineures dans l'interprétation des motifs d'expression rationnelle utilisés dans les filtres `like_regex`, comme décrit dans Section 9.16.2.3.

#### 9.16.2.1. Modes strict et permissif

Quand vous requêtez des données JSON, l'expression de chemin pourrait ne pas correspondre à la structure de données JSON actuelle. Une tentative d'accéder à un membre inexistant d'un objet ou d'un élément d'un tableau résulterait en une erreur de structure. Les expressions de chemin SQL/JSON ont deux modes pour la gestion des erreurs de structure :

- lax (permissif, par défaut) -- le moteur de chemin adapte implicitement la donnée requêtée au chemin spécifié. Toute erreur de structure restante est supprimée et convertie en des séquences SQL/JSON vides.

- strict -- si une erreur de structure survient, une erreur est levée.

Le mode permissif facilite la correspondance de la structure d'un document JSON et celle d'une expression de chemin si la donnée JSON n'est pas conforme au schéma attendu. Si un opérande ne correspond pas aux demandes d'une opération particulière, il peut être automatiquement intégré à un tableau SQL/JSON ou déballé en convertissant ses éléments en une séquence SQL/JSON avant de réaliser cette opération. De plus, les opérateurs de comparaison déballent automatiquement leurs opérandes dans le mode permissif, donc vous pouvez directement comparer les tableaux SQL/JSON. Un tableau de taille 1 est considéré égal à son seul élément. Le déballage automatique n'est pas réaliser si :

- L'expression de chemin contient les méthodes `type()` ou `size()` qui renvoient respectivement le type et le nombre d'éléments dans le tableau.

- Les données JSON requêtées contiennent des tableaux imbriqués. Dans ce cas, seul le tableau externe est déballé alors que les tableaux internes restent inchangés. De ce fait, le déballage implicite peut seulement descendre d'un niveau à chaque étape d'évaluation du chemin.

Par exemple, lors du requêtage de données GPS ci-dessus, vous pouvez faire abstraction du fait qu'il stocke un tableau de segments en utilisant le mode permissif :

    lax $.track.segments.location

Dans le mode strict, le chemin spécifié doit correspondre exactement à la structure du document JSON requêté pour renvoyer un élément SQL/JSON, donc utiliser cette expression de chemin causera une erreur. Pour obtenir le même résultat que dans le mode permissif, vous devez explicitement déballer le tableau `segments` :

    strict $.track.segments[*].location

L'accesseur `.**` peut apporter des résultats surprenants lors de l'utilisation du mode non strict. Par exemple, la requête suivante sélectionne chaque valeur `HR` deux fois :

    lax $.**.HR

Ceci survient parce que l'accesseur `.**` sélectionne à la fois le tableau de `segments` et chacun de ses éléments, alors que l'accesseur `.HR` déballe automatiquement les tableaux lors de l'utilisation du mode non strict. Pour éviter des résultats surprenants, nous recommandons d'utiliser l'accesseur `.**` uniquement dans le mode strict. la requête suivant sélectionne chaque valeur `HR` une seule fois :

    strict $.**.HR

#### 9.16.2.2. Opérateurs et méthodes de chemin SQL/JSON

Tableau 9.48 montre les opérateurs et méthodes disponibles pour `jsonpath`. Notez que, bien que les opérateurs et méthodes unaires puissent être appliqués à de nombreuses valeurs résultant d'une étape de chemin précédente, les opérateurs binaires (addition etc.) peuvent seulement être appliqués à des valeurs seules.

Tableau 9.48. Opérateurs et méthodes `jsonpath`

Opérateur/Méthode Description Exemple(s)
`number` `+` `number` → ``number`` Addition `jsonb_path_query('[2]', '$[0] + 3')` → `5`
`+` `number` → ``number`` Plus unaire (pas d'opération) ; contrairement à l'addition, ceci peut itérer sur plusieurs valeurs `jsonb_path_query_array('{"x": [2,3,4]}', '+ $.x')` → `[2, 3, 4]`
`number` `-` `number` → ``number`` Soustraction `jsonb_path_query('[2]', '7 - $[0]')` → `5`
`-` `number` → ``number`` Négation ; contrairement à la soustraction, ceci peut itérer sur plusieurs valeurs `jsonb_path_query_array('{"x": [2,3,4]}', '- $.x')` → `[-2, -3, -4]`
`number` `*` `number` → ``number`` Multiplication `jsonb_path_query('[4]', '2 * $[0]')` → `8`
`number` `/` `number` → ``number`` Division `jsonb_path_query('[8.5]', '$[0] / 2')` → `4.2500000000000000`
`number` `%` `number` → ``number`` Modulo (reste) `jsonb_path_query('[32]', '$[0] % 10')` → `2`
`value` `.` `type()` → ``string`` Type de l'élément JSON (voir `json_typeof`) `jsonb_path_query_array('[1, "2", {}]', '$[*].type()')` → `["number", "string", "object"]`
`value` `.` `size()` → ``number`` Taille de l'élément JSON (nombre d'éléments d'un tableau, ou 1 si ce n'est pas un tableau) `jsonb_path_query('{"m": [11, 15]}', '$.m.size()')` → `2`
`value` `.` `double()` → ``number`` Nombre flottant approximatif converti en nombre JSON ou en chaîne `jsonb_path_query('{"len": "1.9"}', '$.len.double() * 2')` → `3.8`
`number` `.` `ceiling()` → ``number`` Entier le plus proche, plus grand ou égal au nombre donné `jsonb_path_query('{"h": 1.3}', '$.h.ceiling()')` → `2`
`number` `.` `floor()` → ``number`` Entier le plus proche, plus petit ou égal au nombre donné `jsonb_path_query('{"h": 1.7}', '$.h.floor()')` → `1`
`number` `.` `abs()` → ``number`` Valeur absolue du nombre donné `jsonb_path_query('{"z": -0.3}', '$.z.abs()')` → `0.3`
`string` `.` `datetime()` → ``datetime_type`` (voir note) Valeur date/heure convertie en chaîne `jsonb_path_query('["2015-8-1", "2015-08-12"]', '$[*] ? (@.datetime() < "2015-08-2".datetime())')` → `"2015-8-1"`
`string` `.` `datetime(`template`)` → ``datetime_type`` (voir note) Valeur date/heure convertie en une chaîne en utilisant le modèle `to_timestamp` indiqué `jsonb_path_query_array('["12:30", "18:40"]', '$[*].datetime("HH24:MI")')` → `["12:30:00", "18:40:00"]`
`object` `.` `keyvalue()` → ``array`` Les paires clé-valeur de l'objet, représentées sous la forme d'un tableau d'objets contenant trois champs : `"key"`, `"value"` et `"id"` ; `"id"` est un identifiant unique de l'objet auquel la paire clé-valeur appartient `jsonb_path_query_array('{"x": "20", "y": 32}', '$.keyvalue()')` → `[{"id": 0, "key": "x", "value": "20"}, {"id": 0, "key": "y", "value": 32}]`

### Note

Le type de résultat des méthodes `datetime()` et `datetime(`template`)` peut être `date`, `timetz`, `time`, `timestamptz` ou `timestamp`. Les deux méthodes déterminent dynamiquement le type du résultat.

La méthode `datetime()` trie en séquence pour faire correspondre sa chaîne en entrée aux formats ISO pour les types `date`, `timetz`, `time`, `timestamptz` et `timestamp`. Elle s'arrête au premier format correspondant et émet le type de données correspondant.

La méthode `datetime(`template`)` détermine le type de résultat suivant les champs utilisés dans la chaîne modèle fournie.

Les méthodes `datetime()` et `datetime(`template`)` utilisent les mêmes règles d'analyse que la fonction SQL `to_timestamp` (voir Section 9.8), avec trois exceptions. Tout d'abord, ces méthodes n'autorisent pas les motifs de modèle sans correspondance. Ensuite, seuls les séparateurs suivants sont autorisés dans la chaîne modèle : signe moins, point, barre oblique, virgule, apostrophe, point-virgule, deux-points et espace. Enfin, les séparateurs dans la chaîne modèle doivent correspondre exactement à la chaîne en entrée.

Si différents types date/heure doivent être comparés, une conversion implicite est appliquée. Une valeur `date` peut être convertie en `timestamp` ou `timestamptz`, une valeur `timestamp` peut être convertie en `timestamptz`, et une valeur `time` en `timetz`. Néanmoins, toutes sauf la première de ces conversions dépendent du paramétrage actuel de TimeZone, et de ce fait peuvent seulement être réalisées à travers les fonctions `jsonpath` sensibles au fuseau horaire.

Tableau 9.49 montre les éléments d'expression de filtre disponibles.

Tableau 9.49. Éléments d'expression de filtre `jsonpath`

Prédicat/valeur Description Exemple(s)
`value` `==` `value` → `boolean` Comparaison d'égalité (ceci, et les autres opérateurs de comparaison, fonctionnent sur toutes les valeurs scalaires JSON) `jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == 1)')` → `[1, 1]` `jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == "a")')` → `["a"]`
`value` `!=` `value` → `boolean` `value` `<>` `value` → `boolean` Comparaison de non égalité `jsonb_path_query_array('[1, 2, 1, 3]', '$[*] ? (@ != 1)')` → `[2, 3]` `jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <> "b")')` → `["a", "c"]`
`value` `<` `value` → `boolean` Comparaison inférieur `jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ < 2)')` → `[1]`
`value` `<=` `value` → `boolean` Comparaison inférieur ou égal `jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <= "b")')` → `["a", "b"]`
`value` `>` `value` → `boolean` Comparaison supérieur `jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ > 2)')` → `[3]`
`value` `>=` `value` → `boolean` Comparaison supérieur ou égal `jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ >= 2)')` → `[2, 3]`
`true` → `boolean` Constante JSON `true` `jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == true)')` → `{"name": "Chris", "parent": true}`
`false` → `boolean` Constante JSON `false` `jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == false)')` → `{"name": "John", "parent": false}`
`null` → ``value`` Constante JSON `null` (notez que, contrairement au SQL, la comparaison avec `null` fonctionne normalement) `jsonb_path_query('[{"name": "Mary", "job": null}, {"name": "Michael", "job": "driver"}]', '$[*] ? (@.job == null) .name')` → `"Mary"`
`boolean` `&&` `boolean` → `boolean` AND booléen `jsonb_path_query('[1, 3, 7]', '$[*] ? (@ > 1 && @ < 5)')` → `3`
`boolean` `||` `boolean` → `boolean` OR booléen `jsonb_path_query('[1, 3, 7]', '$[*] ? (@ < 1 || @ > 5)')` → `7`
`!` `boolean` → `boolean` NOT booléen `jsonb_path_query('[1, 3, 7]', '$[*] ? (!(@ < 5))')` → `7`
`boolean` `is unknown` → `boolean` Teste si une condition booléenne est `unknown`. `jsonb_path_query('[-1, 2, 7, "foo"]', '$[*] ? ((@ > 0) is unknown)')` → `"foo"`
`string` `like_regex` `string` [ `flag` `string` ] → `boolean` Teste si le premier opérande correspond à l'expression rationnelle donnée par le deuxième opérande, optionnellement avec les modifications décrites par une chaîne avec les caractères de `flag` (voir Section 9.16.2.3). `jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c")')` → `["abc", "abdacb"]` `jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c" flag "i")')` → `["abc", "aBdC", "abdacb"]`
`string` `starts with` `string` → `boolean` Teste si le deuxième opérande est une sous-chaîne initiale du premier opérande. `jsonb_path_query('["John Smith", "Mary Stone", "Bob Johnson"]', '$[*] ? (@ starts with "John")')` → `"John Smith"`
`exists` `(` `path_expression` `)` → `boolean` Teste si une expression de chemin correspond à au moins un élément SQL/JSON. Renvoie `unknown` si l'expression de chemin retourne une erreur ; le deuxième exemple utilise ceci pour éviter une erreur de clé inexistante dans le mode strict. `jsonb_path_query('{"x": [1, 2], "y": [2, 4]}', 'strict $.* ? (exists (@ ? (@[*] > 2)))')` → `[2, 4]` `jsonb_path_query_array('{"value": 41}', 'strict $ ? (exists (@.name)) .name')` → `[]`

#### 9.16.2.3. Expressions rationnelles SQL/JSON

Les expressions de chemin SQL/JSON permettent la correspondance de texte selon une expression rationnelle avec le filtre `like_regex`. Par exemple, la requête de chemin SQL/JSON suivante correspondrait, sans sensibilité à la casse, à toutes les chaînes d'un tableau commençant avec une voyelle anglaise :

    $[*] ? (@ like_regex "^[aeiou]" flag "i")

La chaîne optionnelle `flag` pourrait inclure un ou plusieurs caractères : `i` pour une recherche insensible à la casse, `m` pour autoriser `^` et `$` à correspondre aux nouvelles lignes, `s` pour autoriser `.` à correspondre à une nouvelle ligne, et `q` pour englober le motif complet (réduisant le comportement à une simple correspondance de sous-chaîne).

Le standard SQL/JSON emprunte sa définition d'expressions rationnelles de l'opérateur `LIKE_REGEX` qui, à son tour, utilise le standard XQuery. PostgreSQL n'accepte pas actuellement l'opérateur `LIKE_REGEX`. De ce fait, le filtre `like_regex` est implémenté en utilisant le moteur d'expression rationnelle POSIX décrit dans Section 9.7.3. Ceci amène différentes variations mineures du comportement du standard SQL/JSON, listées dans Section 9.7.3.8. Notez, néanmoins, que les incompatibilités au niveau des lettres du drapeau décrites ici ne s'appliquent pas à SQL/JSON, car elles traduisent les lettres drapeau de XQuery pour correspondre à ce que le moteur POSIX attend.

Gardez en tête que l'argument motif de `like_regex` est une chaîne littérale de chemin JSON, écrite suivant les règles données dans Section 8.14.7. Ceci signifie en particulier que tout antislash utilisé dans l'expression rationnelle doit être doublé. Par exemple, pour établir une correspondance aux valeurs de type chaîne de caractères du document racine ne contenant que des chiffres :

    $.* ? (@ like_regex "^\\d+$")