PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 17 RC1 » Langage SQL » Fonctions et opérateurs » Fonctions et opérateurs JSON

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

  • les fonctions de requêtage SQL/JSON

Pour fournir un support natif des types de données JSON dans un environnement SQL, PostgreSQL implémente le modèle de données SQL/JSON. Ce modèle comprends des séquences d'éléments. Chaque élément peut contenir des valeurs SQL scalaires, avec une valeur null SQL/JSON supplémentaire, et des structures de données composites qui utilisent les tableaux et objets JSON. Le modèle est une formalisation du modèle de données compris dans la spécification JSON de la RFC 7159.

SQL/JSON vous permet de gérer des données JSON parmi les données SQL habituelles avec un support des transactions, incluant :

  • Le chargement de données JSON dans la base de données et son stockage dans des colonnes SQL standards, tout comme des chaînes de caractères ou des chaînes binaires.

  • La génération d'objets JSON et de tableaux à partir de données relationnelles.

  • Le requêtage de données JSON en utilisant les fonctions de requêtage SQL/JSON et les expressions du 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.45 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.45. Opérateurs json et jsonb

Opérateur

Description

Exemple(s)

json -> integerjson

jsonb -> integerjsonb

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 -> textjson

jsonb -> textjsonb

Extrait le champ objet JSON avec la clé donnée.

'{"a": {"b":"foo"}}'::json -> 'a'{"b":"foo"}

json ->> integertext

jsonb ->> integertext

Extrait le n-ième élément d'un tableau JSON, comme le text.

'[1,2,3]'::json ->> 23

json ->> texttext

jsonb ->> texttext

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.46. 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.46. Opérateurs jsonb supplémentaires

Opérateur

Description

Exemple(s)

jsonb @> jsonbboolean

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}'::jsonbt

jsonb <@ jsonbboolean

Est-ce que la première valeur JSON est contenue dans la seconde ?

'{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonbt

jsonb ? textboolean

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 || jsonbjsonb

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 - textjsonb

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 - integerjsonb

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 @? jsonpathboolean

Est-ce que le chemin JSON renvoie tout élément pour la valeur JSON spécifiée ? (Ceci est utile seulement avec les expressions de chemin JSON du standard SQL, pas avec les expressions de vérification du prédicat, car ces dernières renvoient toujours une valeur.)

'{"a":[1,2,3,4,5]}'::jsonb @? '$.a[*] ? (@ > 2)'t

jsonb @@ jsonpathboolean

Renvoie le résultat d'une vérification de prédicat du chemin JSON pour la valeur JSON indiquée. (Cela n'est utile qu'avec les expressions de vérification de prédicat, et non avec les expressions de chemin JSON du standard SQL, car il renverra NULL si le résultat du chemin n'est pas une seule valeur booléenne.)

'{"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.47 montre les fonctions disponibles pour construire des valeurs json et jsonb. Certaines fonctions de cette table ont une clause RETURNING, qui indique le type de données renvoyées. Il doit être parmi json, jsonb, bytea, un type chaîne de caractères (text, char, varchar ou nchar), ou un type qui peut être converti en json. Par défaut, le type json est renvoyé.

Tableau 9.47. 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]]

json_array ( [ { value_expression [ FORMAT JSON ] } [, ...] ] [ { NULL | ABSENT } ON NULL ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

json_array ( [ query_expression ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

Construit un tableau JSON à partir d'une série de paramètres value_expression ou à partir des résultats de query_expression, qui doit être une requête SELECT renvoyant une seule colonne. Si ABSENT ON NULL est précisé, les valeurs NULL sont ignorées. C'est toujours le cas si une query_expression est utilisée.

json_array(1,true,json '{"a":null}')[1, true, {"a":null}]

json_array(SELECT * FROM (VALUES(1),(2)) t)[1, 2]

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 ( [ { key_expression { VALUE | ':' } value_expression [ FORMAT JSON [ ENCODING UTF8 ] ] }[, ...] ] [ { NULL | ABSENT } ON NULL ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

Construit un objet avec toutes les paires clé/valeur données ou un objet vide si aucune n'est donnée. key_expression est une expression scalaire définissant la clé JSON, qui est convertie dans le type text. Elle ne peut pas être NULL et elle ne peut pas appartenir à un type qui a une conversion vers le type json. Si WITH UNIQUE KEYS est indiqué, il ne doit pas y avoir de key_expression dupliqué. Toute paire pour laquelle value_expression vaut NULL est omise de la sortie si ABSENT ON NULL est indiquée ; si NULL ON NULL est indiquée ou si la clause est est omise, la clé est inclue avec la valeur NULL.

json_object('code' VALUE 'P123', 'title': 'Jaws'){"code" : "P123", "title" : "Jaws"}

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"}

json ( expression [ FORMAT JSON [ ENCODING UTF8 ]] [ { WITH | WITHOUT } UNIQUE [ KEYS ]] ) → json

Convertit une expression donnée spécifiée comme une chaîne text ou bytea (en encodage UTF8) en une valeur JSON. Si expression est NULL, une valeur NULL SQL est renvoyée. Si WITH UNIQUE est spécifié, l'expression ne doit pas contenir de doublon (clé d'objet).

json('{"a":123, "b":[true,"foo"], "a":"bar"}'){"a":123, "b":[true,"foo"], "a":"bar"}

json_scalar ( expression )

Convertit une valeur scalaire SQL donnée en une valeur scalaire JSON. Si l'entrée est NULL, une valeur NULL SQL est renvoyée. Si l'entrée est un nombre ou une valeur booléenne, une valeur numérique ou booléenne correspondante en JSON est renvoyée. Pour toute autre valeur, une chaîne JSON est renvoyée.

json_scalar(123.45)123.45

json_scalar(CURRENT_TIMESTAMP)"2022-05-10T10:51:04.62128-04:00"

json_serialize ( expression [ FORMAT JSON [ ENCODING UTF8 ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ] )

Convertit une expression SQL/JSON en une chaîne de caractères ou en une chaîne binaire. L'expression peut être de n'importe quel type JSON, ou chaîne de caractères, ou bytea en encodage UTF8. Le type renvoyé utilisé dans RETURNING peut être n'importe quel type de chaîne de caractères ou bytea. Le type par défaut est text.

json_serialize('{ "a" : 1 } ' RETURNING bytea)\x7b20226122203a2031207d20

[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.48 détaille les possibilités de SQL/JSON pour tester du JSON.

Tableau 9.48. Fonctions de test SQL/JSON

Fonction

Description

Exemple(s)

expression IS [ NOT ] JSON [ { VALUE | SCALAR | ARRAY | OBJECT } ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ]

Ce prédicat teste si expression peut être analysé comme du JSON, possiblement d'un type indiqué. Si SCALAR, ARRAY ou OBJECT est précisé, le test revient à savoir si le JSON est de ce type spécifique. Si WITH UNIQUE KEYS est précisé, alors tout objet dans l'expression est aussi testé pour voir s'il contient des clés dupliquées.

SELECT js,
  js IS JSON "json?",
  js IS JSON SCALAR "scalar?",
  js IS JSON OBJECT "object?",
  js IS JSON ARRAY "array?"
FROM (VALUES
      ('123'), ('"abc"'), ('{"a": "b"}'), ('[1,2]'),('abc')) foo(js);
     js     | json? | scalar? | object? | array?
------------+-------+---------+---------+--------
 123        | t     | t       | f       | f
 "abc"      | t     | t       | f       | f
 {"a": "b"} | t     | f       | t       | f
 [1,2]      | t     | f       | f       | t
 abc        | f     | f       | f       | f

SELECT js,
  js IS JSON OBJECT "object?",
  js IS JSON ARRAY "array?",
  js IS JSON ARRAY WITH UNIQUE KEYS "array w. UK?",
  js IS JSON ARRAY WITHOUT UNIQUE KEYS "array w/o UK?"
FROM (VALUES ('[{"a":"1"},
 {"b":"2","b":"3"}]')) foo(js);
-[ RECORD 1 ]-+--------------------
js            | [{"a":"1"},        +
              |  {"b":"2","b":"3"}]
object?       | f
array?        | t
array w. UK?  | f
array w/o UK? | t


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

Tableau 9.49. 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")
       

jsonb_populate_record_valid ( base anyelement, from_json json ) → boolean

Fonction pour tester jsonb_populate_record. Renvoie true si l'entrée jsonb_populate_record se termine sans aucune erreur pour l'objet JSON donné ; c'est-à-dire, si l'entrée est valide, sinon false.

create type jsb_char2 as (a char(2));

select jsonb_populate_record_valid(NULL::jsb_char2, '{"a": "aaa"}');

 jsonb_populate_record_valid
-----------------------------
 f
(1 row)

select * from jsonb_populate_record(NULL::jsb_char2, '{"a": "aaa"}') q;

ERROR:  value too long for type character(2)

select jsonb_populate_record_valid(NULL::jsb_char2, '{"a": "aa"}');

 jsonb_populate_record_valid
-----------------------------
 t
(1 row)

select * from jsonb_populate_record(NULL::jsb_char2, '{"a": "aa"}') q;

 a
----
 aa
(1 row)

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. (Cela n'est utile qu'avec les expressions de chemin JSON standard SQL, et non avec les expressions de vérification de prédicat, car celles-ci renvoient toujours une valeur.) 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. (Cela n'est utile qu'avec les expressions de vérification de prédicat, et non avec les expressions de chemin JSON standard SQL, car cela échouera ou renverra NULL si le résultat du chemin n'est pas une seule valeur booléenne.) 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. Pour les expressions de chemin JSON standard SQL, il renvoie les valeurs JSON sélectionnées à partir de target. Pour les expressions de vérification de prédicat, il renvoie le résultat de la vérification du prédicat : true, false ou null. 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 paramètres sont les mêmes que pour jsonb_path_query

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 ou NULL s'il n'y a pas de résultat. Les paramètres sont les mêmes que pour jsonb_path_query

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 NULLt


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, de façon similaire 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é. S'il n'y a pas de correspondance, le résultat sera NULL, false, ou une erreur, selon la fonction. 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. Le premier élement du chemin doit toujours être $. 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 d'accès agit sur le(s) résultat(s) de l'étape d'évaluation précédente, produisant zéro, un ou plusieurs éléments de sortie à partir de chaque élément d'entrée.

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

SELECT '{
  "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
      }
    ]
  }
}' AS json \gset
  

(L'exemple ci-dessus peut être copié-collé dans psql pour préparer les exemples suivants. Ensuite, psql remplacera :'json' par une constante de chaîne de caractère, contenant la valeur JSON.)

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, par exemple :

=> select jsonb_path_query(:'json', '$.track.segments');
                                                                         jsonb_path_query
-----------------------------------------------------------​-----------------------------------------------------------​---------------------------------------------
 [{"HR": 73, "location": [47.763, 13.4034], "start time": "2018-10-14 10:05:14"}, {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}]

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

=> select jsonb_path_query(:'json', '$.track.segments[*].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]

Ici, nous avons commencé avec l'intégralité de la valeur d'entrée JSON ($), puis l'opérateur d'accès .track a sélectionné l'objet JSON associé à la clé d'objet "track", ensuite l'opérateur d'accès .segments a sélectionné le tableau JSON associé à la clé "segments" dans cet objet, puis l'opérateur d'accès [*] a sélectionné chaque élément de ce tableau (produisant une série d'éléments), enfin l'opérateur d'accès .location a sélectionné le tableau JSON associé à la clé "location" dans chacun de ces objets. Dans cet exemple, chacun de ces objets avait une clé "location" ; maissi si l'un d'eux ne l'avait pas, l'opérateur d'accès .location n'aurait pas donnée d'élement de sortie pour cet élément d'entrée.

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 :

=> select jsonb_path_query(:'json', '$.track.segments[0].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]

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.3. Chaque nom de méthode doit être précédé d'un point. Par exemple, vous pouvez obtenir la taille d'un tableau :

=> select jsonb_path_query(:'json', '$.track.segments.size()');
 jsonb_path_query
------------------
 2

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.3.

Un chemin peut aussi contenir 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 produire 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.51. À l'intérieur d'une expression de filtre, la variable @ dénote la valeur en cours de considération (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 ainsi :

=> select jsonb_path_query(:'json', '$.track.segments[*].HR ? (@ > 130)');
 jsonb_path_query
------------------
 135

Pour obtenir les heures de début des segments ayant une telle valeur, vous devez filtrer les segments incompatibles avant de sélectionner 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 :

=> select jsonb_path_query(:'json', '$.track.segments[*] ? (@.HR > 130)."start time"');
   jsonb_path_query
-----------------------
 "2018-10-14 10:39:21"

Vous pouvez utiliser plusieurs expressions de filtre en séquence, si nécessaire. 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 :

=> select jsonb_path_query(:'json', '$.track.segments[*] ? (@.location[1] < 13.4) ? (@.HR > 130)."start time"');
   jsonb_path_query
-----------------------
 "2018-10-14 10:39:21"

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 :

=> select jsonb_path_query(:'json', '$.track.segments[*] ? (@.location[1] < 13.4).HR ? (@ > 130)');
 jsonb_path_query
------------------
 135

Vous pouvez aussi imbriquer les expressions de filtre. Cet exemple renvoie la taille du chemin s'il contient des segments ayant des valeurs de fréquence cardiaque élevées ou une séquence vide sinon :

=> select jsonb_path_query(:'json', '$.track ? (exists(@.segments[*] ? (@.HR > 130))).segments.size()');
 jsonb_path_query
------------------
 2

9.16.2.1. Déviations du standard SQL #

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

9.16.2.1.1. Expressions de la vérification du prédicat booléen #

Étant une extension du standard SQL, une expression de chemin PostgreSQL peut être un prédicat booléen, alors que le standard SQL autorise les prédicats uniquement dans les filtres. Tandis que les expressions de chemin conformes au standard SQL renvoient les éléments pertinents de la valeur JSON interrogée, les expressions de vérification de prédicat renvoient le résultat unique du prédicat avec trois valeurs possibles : true, false ou unknown. Par exemple, nous pourrions écrire cette expression de filtre qui est conforme au standard SQL :

=> select jsonb_path_query(:'json', '$.track.segments ?(@[*].HR > 130)');
                                jsonb_path_query
-----------------------------------------------------------​----------------------
 {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}

L'expression de vérification de prédicat similaire renvoie simplement true, indiquant qu'une correspondance existe :

=> select jsonb_path_query(:'json', '$.track.segments[*].HR > 130');
 jsonb_path_query
------------------
 true

Note

Les expressions de vérification de prédicat sont requises dans l'opérateur @@ (et la fonction jsonb_path_match), et ne doivent pas être utilisées avec l'opérateur @? (ou la fonction jsonb_path_exists).

9.16.2.1.2. Interprétation des expressions régulières #

Il existe de légères différences dans l'interprétation des modèles d'expressions régulières utilisés dans les filtres like_regex, comme décrit dans Section 9.16.2.4.

9.16.2.2. 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 est définie comme 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 qui ne peut être corrigée comme décrit ci-dessous est supprimée, ne produisant aucune correspondance.

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

Le mode permissif facilite la correspondance d'un document JSON et 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éalisé quand :

  • 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 :

=> select jsonb_path_query(:'json', 'lax $.track.segments.location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]

Dans le mode strict, le chemin spécifié doit correspondre exactement à la structure du document JSON requêté, donc utiliser cette expression de chemin causera une erreur :

=> select jsonb_path_query(:'json', 'strict $.track.segments.location');
ERROR:  jsonpath member accessor can only be applied to an object

Pour obtenir le même résultat qu'en mode lax, vous devez déballer explicitement le tableau segments :

=> select jsonb_path_query(:'json', 'strict $.track.segments[*].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]

Le comportement de décapsulation (unwrapping) en mode lax peut entraîner des résultats surprenants. Par exemple, la requête suivante utilisant l'opérateur d'accès .** sélectionne chaque valeur HR deux fois :

=> select jsonb_path_query(:'json', 'lax $.**.HR');
 jsonb_path_query
------------------
 73
 135
 73
 135

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 :

=> select jsonb_path_query(:'json', 'strict $.**.HR');
 jsonb_path_query
------------------
 73
 135

La décapsulation (unwrapping) des tableaux peut également entraîner des résultats inattendus. Considérez cet exemple, qui sélectionne tous les tableaux location :

=> select jsonb_path_query(:'json', 'lax $.track.segments[*].location');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 rows)

Comme prévu, il renvoie les tableaux complets. Mais l'application d'une expression de filtre entraîne la décapsulation (unwrapping) des tableaux pour évaluer chaque élément, ne renvoyant que les éléments qui correspondent à l'expression :

=> select jsonb_path_query(:'json', 'lax $.track.segments[*].location ?(@[*] > 15)');
 jsonb_path_query
------------------
 47.763
 47.706
(2 rows)

Ceci malgré le fait que les tableaux complets sont sélectionnés par l'expression de chemin. Utilisez le mode strict pour restaurer la sélection des tableaux :

=> select jsonb_path_query(:'json', 'strict $.track.segments[*].location ?(@[*] > 15)');
 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 rows)

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

Tableau 9.50 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. En mode lax, les méthodes appliquées à un tableau seront exécutées pour chaque valeur du tableau. Les exceptions sont : .type() et .size(), qui s'appliquent au tableau lui-même.

Tableau 9.50. Opérateurs et méthodes jsonpath

Opérateur/Méthode

Description

Exemple(s)

number + numbernumber

Addition

jsonb_path_query('[2]', '$[0] + 3')5

+ numbernumber

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 - numbernumber

Soustraction

jsonb_path_query('[2]', '7 - $[0]')5

- numbernumber

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 * numbernumber

Multiplication

jsonb_path_query('[4]', '2 * $[0]')8

number / numbernumber

Division

jsonb_path_query('[8.5]', '$[0] / 2')4.2500000000000000

number % numbernumber

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 . boolean()boolean

Valeur booléenne convertie à partir d'un booléen, d'un nombre ou d'une chaîne JSON

jsonb_path_query_array('[1, "yes", false]', '$[*].boolean()')[true, true, false]

value . string()string

Valeur de type chaîne de caractères convertie en un booléen, nombre, chaîne ou horodatage JSON

jsonb_path_query_array('[1.23, "xyz", false]', '$[*].string()')["1.23", "xyz", "false"]

jsonb_path_query('"2023-08-15"', '$.datetime().string()')"2023-08-15"

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

value . bigint()bigint

Grande valeur entière convertie à partir d'un nombre JSON ou d'une chaîne JSON

jsonb_path_query('{"len": "9876543219"}', '$.len.bigint()')9876543219

value . decimal( [ precision [ , scale ] ] )decimal

Valeur décimale arrondie convertie à partir d'un nombre JSON ou d'une chaîne JSON. precision et scale doivent être des valeurs entières.

jsonb_path_query('1234.5678', '$.decimal(6, 2)')1234.57

value . integer()integer

Valeur entière convertie à partir d'un nombre JSON ou d'une chaîne JSON

jsonb_path_query('{"len": "12345"}', '$.len.integer()')12345

value . number()numeric

Valeur numérique convertie à partir d'un nombre JSON ou d'une chaîne JSON

jsonb_path_query('{"len": "123.45"}', '$.len.number()')123.45

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"]

string . date()date

Valeur date convertie en chaîne

jsonb_path_query('"2023-08-15"', '$.date()')"2023-08-15"

string . time()time without time zone

Horodatage sans fuseau horaire converti en chaîne

jsonb_path_query('"12:34:56"', '$.time()')"12:34:56"

string . time(precision)time without time zone

Valeur horaire sans fuseau horaire convertie en chaîne de caractères, avec les secondes fractionnelles converties à la précision demandée.

jsonb_path_query('"12:34:56.789"', '$.time(2)')"12:34:56.79"

string . time_tz()time with time zone

Valeur horaire avec fuseau horaire convertie à partir d'une chaîne de caractères.

jsonb_path_query('"12:34:56 +05:30"', '$.time_tz()')"12:34:56+05:30"

string . time_tz(precision)time with time zone

Valeur horaire avec fuseau horaire convertie à partir d'une chaîne de caractères, avec les secondes fractionnelles converties à la précision demandée.

jsonb_path_query('"12:34:56.789 +05:30"', '$.time_tz(2)')"12:34:56.79+05:30"

string . timestamp()timestamp without time zone

Horodatage sans fuseau horaire converti à partir d'une chaîne

jsonb_path_query('"2023-08-15 12:34:56"', '$.timestamp()')"2023-08-15T12:34:56"

string . timestamp(precision)timestamp without time zone

Horodatage sans fuseau horaire converti à partir d'une chaîne, avec des secondes fractionnaires ajustées à la précision donnée.

jsonb_path_query('"2023-08-15 12:34:56.789"', '$.timestamp(2)')"2023-08-15T12:34:56.79"

string . timestamp_tz()timestamp with time zone

Horodatage avec fuseau horaire converti à partir d'une chaîne

jsonb_path_query('"2023-08-15 12:34:56 +05:30"', '$.timestamp_tz()')"2023-08-15T12:34:56+05:30"

string . timestamp_tz(precision)timestamp with time zone

Horodatage avec fuseau horaire converti à partir d'une chaîne, avec des secondes fractionnaires ajustées à la précision donnée.

jsonb_path_query('"2023-08-15 12:34:56.789 +05:30"', '$.timestamp_tz(2)')"2023-08-15T12:34:56.79+05:30"

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. De même, d'autres méthodes liées aux dates/heures qui convertissent des chaînes en types de date/heure effectuent également cette conversion, qui peut impliquer le paramètre TimeZone actuel. Par conséquent, ces conversions ne peuvent être effectuées que si les fonctions jsonpath sont conscientes du fuseau horaire.

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

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

Prédicat/valeur

Description

Exemple(s)

value == valueboolean

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 != valueboolean

value <> valueboolean

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 < valueboolean

Comparaison inférieur

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ < 2)')[1]

value <= valueboolean

Comparaison inférieur ou égal

jsonb_path_query_array('["a", "b", "c"]', '$[*] ? (@ <= "b")')["a", "b"]

value > valueboolean

Comparaison supérieur

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ > 2)')[3]

value >= valueboolean

Comparaison supérieur ou égal

jsonb_path_query_array('[1, 2, 3]', '$[*] ? (@ >= 2)')[2, 3]

trueboolean

Constante JSON true

jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == true)'){"name": "Chris", "parent": true}

falseboolean

Constante JSON false

jsonb_path_query('[{"name": "John", "parent": false}, {"name": "Chris", "parent": true}]', '$[*] ? (@.parent == false)'){"name": "John", "parent": false}

nullvalue

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 && booleanboolean

AND booléen

jsonb_path_query('[1, 3, 7]', '$[*] ? (@ > 1 && @ < 5)')3

boolean || booleanboolean

OR booléen

jsonb_path_query('[1, 3, 7]', '$[*] ? (@ < 1 || @ > 5)')7

! booleanboolean

NOT booléen

jsonb_path_query('[1, 3, 7]', '$[*] ? (!(@ < 5))')7

boolean is unknownboolean

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.4).

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 stringboolean

Vérifie 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

Vérifie si une expression de chemin correspond à au moins un élément SQL/JSON. Renvoie unknown si l'expression de chemin entraînerait une erreur ; le deuxième exemple utilise cela pour éviter une erreur de type clé inexistante en utilisant 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.4. Expressions rationnelles SQL/JSON #

Les expressions de chemin SQL/JSON permettent de faire correspondre du texte à une expression régulière avec le filtre like_regex. Par exemple, la requête de chemin SQL/JSON suivante ferait correspondre, de manière insensible à la casse, toutes les chaînes d'un tableau commençant par une voyelle française :

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

La chaîne de flag optionnelle peut inclure un ou plusieurs des caractères suivants : i pour une correspondance insensible à la casse, m pour permettre à ^ et $ de correspondre aux nouvelles lignes, s pour permettre à . de correspondre à une nouvelle ligne, q pour citer l'ensemble du motif (réduisant le comportement à une simple correspondance de sous-chaîne).

La norme SQL/JSON emprunte sa définition pour les expressions régulières à l'opérateur LIKE_REGEX, qui utilise à son tour la norme XQuery. PostgreSQL ne prend actuellement pas en charge l'opérateur LIKE_REGEX. Par conséquent, le filtre like_regex est implémenté en utilisant le moteur d'expressions régulières POSIX décrit dans Section 9.7.3. Cela conduit à plusieurs petites divergences par rapport au comportement standard SQL/JSON, qui sont cataloguées dans Section 9.7.3.8. Notez toutefois que les incompatibilités de lettres du drapeau (flag) décrites ici ne s'appliquent pas à SQL/JSON, car il traduit les lettres du drapeau XQuery pour correspondre à ce que le moteur POSIX attend.

Gardez à l'esprit que l'argument de motif de like_regex est une chaîne littérale de chemin JSON, écrite selon les règles données dans Section 8.14.7. Cela signifie en particulier que tous les antislashs que vous souhaitez utiliser dans l'expression régulière doivent être doublés. Par exemple, pour faire correspondre les valeurs de chaîne du document racine qui ne contiennent que des chiffres :

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

9.16.3. Fonctions de requêtage SQL/JSON #

Les fonctions SQL/JSON JSON_EXISTS(), JSON_QUERY() et JSON_VALUE() décrites dans Tableau 9.52 peuvent être utilisées pour interroger des documents JSON. Chacune de ces fonctions applique une path_expression (la requête de chemin SQL/JSON) à un context_item (le document). Voir Section 9.16.2 pour plus de détails sur ce que peut contenir une path_expression. Le path_expression peut aussi référencer des variables, dont les valeurs sont indiquées avec leur nom respectif dans la clause PASSING qui est acceptée par chaque fonction. context_item peut être une valeur jsonb ou une chaîne de caractères convertible en jsonb.

Tableau 9.52. Fonctions de requête SQL/JSON

Signature de la fonction

Description

Exemple(s)

JSON_EXISTS (
context_item, path_expression
[ PASSING { value AS varname } [, ...]]
[{ TRUE | FALSE | UNKNOWN | ERROR } ON ERROR ]) → boolean

  • Renvoie true si le path_expression SQL/JSON appliquée au context_item produit des éléments. Sinon renvoie false.

  • La clause ON ERROR spécifie le comportement en cas d'erreur lors de l'évaluation de path_expression. Indiquer ERROR causera le renvoi d'une erreur avec le message approprié. Les autres options incluent le renvoi de valeurs booléennes FALSE ou TRUE ou la valeur UNKNOWN qui est en réalité un NULL SQL. Par défaut, quand aucune clause ON ERROR n'est indiquée, la valeur booléenne FALSE est renvoyée.

Exemples :

JSON_EXISTS(jsonb '{"key1": [1,2,3]}', 'strict $.key1[*] ? (@ > $x)' PASSING 2 AS x)t

JSON_EXISTS(jsonb '{"a": [1,2,3]}', 'lax $.a[5]' ERROR ON ERROR)f

JSON_EXISTS(jsonb '{"a": [1,2,3]}', 'strict $.a[5]' ERROR ON ERROR)

ERROR:  jsonpath array subscript is out of bounds

JSON_QUERY (
context_item, path_expression
[ PASSING { value AS varname } [, ...]]
[ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ]
[ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ]
[ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ]
[ { ERROR | NULL | EMPTY { [ ARRAY ] | OBJECT } | DEFAULT expression } ON EMPTY ]
[ { ERROR | NULL | EMPTY { [ ARRAY ] | OBJECT } | DEFAULT expression } ON ERROR ]) → jsonb

  • Renvoie le résultat de l'application du path_expression SQL/JSON au context_item.

  • Par défaut, le résultat est renvoyé comme une valeur de type jsonb, bien que la clause RETURNING peut être utilisé pour renvoyer certains autres types vers lesquels ils peuvent être convertis.

  • Si l'expression du chemin peut renvoyer plusieurs valeurs, il pourrait être nécessaire des les englober en utilisant la clause WITH WRAPPER pour la transformer en chaîne JSON valide. Le comportement par défaut revient à ne pas les englober, comme si WITHOUT WRAPPER était indiqué. La clause WITH WRAPPER est considéré comme signifiant WITH UNCONDITIONAL WRAPPER, ce qui signifie que même une valeur seule de résultat sera englobée. Pour appliquer l'englobage uniquement quand plusieurs valeurs sont présentes, précisez WITH CONDITIONAL WRAPPER. Obtenir plusieurs valeurs dans le résultat sera traité comme une erreur si WITHOUT WRAPPER est indiqué.

  • Si le résultat est une chaîne scalaire, par défaut, la valeur renvoyée sera entourée de guillemets simples, en faisant une valeur JSON valide. Cela peut être rendu explicite en spécifiant KEEP QUOTES. Inversement, les guillemets peuvent être omis en spécifiant OMIT QUOTES. Pour s'assurer que le résultat est une valeur JSON valide, OMIT QUOTES ne peut pas être indiqué quand WITH WRAPPER est aussi précisé.

    La clause ON EMPTY indique le comportement si l'évaluation de path_expression renvoie un ensemble vide. La clause ON ERROR indique le comportement si une erreur survient lors de l'évaluation de path_expression, lors de la conversion de la valeur du résultat dans le type de RETURNING, ou lors de l'évaluation de l'expression ON EMPTY si l'évaluation de path_expression renvoie un ensemble vide.

    Pour ON EMPTY et ON ERROR, indiquer ERROR causera le renvoi d'une erreur avec le message approprié. D'autres options incluent le renvoi d'un NULL SQL, d'un tableau vide (EMPTY [ARRAY]), d'un objet vide (EMPTY OBJECT), ou d'une expression utilisateur (DEFAULT expression) qui peut être convertie en jsonb ou dans le type spécifié par RETURNING. La valeur par défaut quand ON EMPTY ou ON ERROR n'est pas indiqué est de renvoyer une valeur SQL NULL.

Exemples :

JSON_QUERY(jsonb '[1,[2,3],null]', 'lax $[*][$off]' PASSING 1 AS off WITH CONDITIONAL WRAPPER)[3]

JSON_QUERY(jsonb '{"a": "[1, 2]"}', 'lax $.a' OMIT QUOTES)[1, 2]

JSON_QUERY(jsonb '{"a": "[1, 2]"}', 'lax $.a' RETURNING int[] OMIT QUOTES ERROR ON ERROR)

ERROR:  malformed array literal: "[1, 2]"
DETAIL:  Missing "]" after array dimensions.

JSON_VALUE (
context_item, path_expression
[ PASSING { value AS varname } [, ...]]
[ RETURNING data_type ]
[ { ERROR | NULL | DEFAULT expression } ON EMPTY ]
[ { ERROR | NULL | DEFAULT expression } ON ERROR ]) → text

  • Renvoie le résultat de l'application du path_expression SQL/JSON au context_item.

  • Utilisez seulement JSON_VALUE() si la valeur extraite doit être un élément scalaire SQL/JSON simple ; la récupération de plusieurs valeurs sera traitée comme une erreur. Si vous vous attendez à ce que la valeur extraite soit un objet ou un tableau, utilisez à la place la fonction JSON_QUERY.

  • Par défaut, le résultat, qui doit être une valeur scalaire simple, est renvoyé comme une valeur de type text, bien que la clause RETURNING puisse être utilisée pour renvoyer d'autres types auxquels il peut être converti.

  • Les clauses ON ERROR et ON EMPTY ont des sémantiques similaires à celles mentionnées dans la description de JSON_QUERY, sauf si l'ensemble de valeurs renvoyées à la place d'une erreur est différent.

  • Notez que les chaînes scalaires renvoyées par JSON_VALUE ont toujours leurs guillemets supprimés, ce qui équivaut à spécifier OMIT QUOTES dans JSON_QUERY.

Exemples :

JSON_VALUE(jsonb '"123.45"', '$' RETURNING float)123.45

JSON_VALUE(jsonb '"03:04 2015-02-01"', '$.datetime("HH24:MI YYYY-MM-DD")' RETURNING date)2015-02-01

JSON_VALUE(jsonb '[1,2]', 'strict $[$off]' PASSING 1 as off)2

JSON_VALUE(jsonb '[1,2]', 'strict $[*]' DEFAULT 9 ON ERROR)9


Note

L'expression context_item est convertie en jsonb par une conversion implicite si l'expression n'est pas déjà de type jsonb. Notez, néanmoins, que toute erreur d'analyse survenant pendant cette conversion, est renvoyée sans condition, c'est-à-dire ne sont pas gérées suivant la clause ON ERROR implicite ou explicite.

Note

JSON_VALUE() renvoie un NULL SQL si path_expression renvoie un JSON null, alors que JSON_QUERY() renvoie le null JSON tel quel.

9.16.4. JSON_TABLE #

JSON_TABLE est une fonction SQL/JSON qui interroge les données JSON et présente les résultats sous forme de vue relationnelle, qui peut être consultée comme une table SQL normale. Vous pouvez utiliser JSON_TABLE dans la clause FROM d'une instruction SELECT, UPDATE ou DELETE et comme source de données dans une instruction MERGE.

En prenant des données JSON en entrée, JSON_TABLE utilise une expression de chemin JSON pour extraire une partie des données fournies à utiliser comme motif de ligne pour la vue construite. Chaque valeur SQL/JSON donnée par le modèle de ligne sert de source pour une ligne distincte dans la vue construite.

Pour diviser le motif de ligne en colonnes, JSON_TABLE fournit la clause COLUMNS qui définit le schéma de la vue créée. Pour chaque colonne, une expression de chemin JSON distincte peut être spécifiée pour être évaluée par rapport au motif de ligne afin d'obtenir une valeur SQL/JSON qui deviendra la valeur de la colonne spécifiée dans une ligne de sortie donnée.

Les données JSON stockées à un niveau imbriqué du modèle de ligne peuvent être extraites à l'aide de la clause NESTED PATH. Chaque clause NESTED PATH peut être utilisée pour générer une ou plusieurs colonnes à partir des données d'un niveau imbriqué du motif de ligne. Ces colonnes peuvent être spécifiées à l'aide d'une clause COLUMNS semblable à la clause COLUMNS de niveau le plus haut. Les lignes construites à partir des colonnes imbriquées sont appelées lignes enfants et sont jointes aux lignes construites à partir des colonnes spécifiées dans la clause COLUMNS parente pour obtenir la ligne dans la vue finale. Les colonnes enfants elles-mêmes peuvent contenir une spécification NESTED PATH, permettant ainsi d'extraire des données situées à des niveaux d'imbrication arbitraires. Les colonnes produites par plusieurs NESTED PATH au même niveau sont considérées comme des frères et sœurs et leurs lignes sont combinées à l'aide de UNION après la jonction avec la ligne parente.

Les lignes produites par JSON_TABLE sont jointes latéralement à la ligne qui les a générées, de sorte que vous n'avez pas besoin de joindre explicitement la vue construite avec la table d'origine contenant les données JSON.

La syntaxe est :

JSON_TABLE (
    context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...] ]
    COLUMNS ( json_table_column [, ...] )
    [ { ERROR | EMPTY [ARRAY]} ON ERROR ]
)

json_table_column vaut :

  name FOR ORDINALITY
  | name type
        [ FORMAT JSON [ENCODING UTF8]]
        [ PATH path_expression ]
        [ { WITHOUT | WITH { CONDITIONAL | [UNCONDITIONAL] } } [ ARRAY ] WRAPPER ]
        [ { KEEP | OMIT } QUOTES [ ON SCALAR STRING ] ]
        [ { ERROR | NULL | EMPTY { [ARRAY] | OBJECT } | DEFAULT expression } ON EMPTY ]
        [ { ERROR | NULL | EMPTY { [ARRAY] | OBJECT } | DEFAULT expression } ON ERROR ]
  | name type EXISTS [ PATH path_expression ]
        [ { ERROR | TRUE | FALSE | UNKNOWN } ON ERROR ]
  | NESTED [ PATH ] path_expression [ AS json_path_name ] COLUMNS ( json_table_column [, ...] )

Chaque élement de syntaxe est décrit ci-dessous avec plus de détails.

context_item, path_expression [ AS json_path_name ] [ PASSING { value AS varname } [, ...]]

context_item indique le document en entrée à requêter, path_expression est une expression de chemin SQL/JSON définissant la requête, et json_path_name est un nom optionnel pour path_expression. La clause optionnelle PASSING fournit des valeurs aux données pour les variables mentionnées dans path_expression. Le résultat de l'évaluation des données en entrée en utilisant les éléments déjà mentionnés est appelé The result of the input data evaluation using the aforementioned elements row pattern, qui est utilisé comme source pour les valeurs de ligne dans la vue construite.

COLUMNS ( json_table_column [, ...] )

La clause COLUMNS définit le schéma de la vue construite. Dans cette clause, vous pouvez spécifier chaque colonne à remplir avec une valeur SQL/JSON obtenue en appliquant une expression de chemin JSON au motif de ligne. json_table_column possède les variantes suivantes :

name FOR ORDINALITY

Ajoute une colonne d'ordinalité qui fournit une numérotation séquentielle des lignes à partir de 1. Chaque NESTED PATH (voir ci-dessous) obtient son propre compteur pour les colonnes d'ordinalité imbriquées.

name type [FORMAT JSON [ENCODING UTF8]] [ PATH path_expression ]

Insère une valeur SQL/JSON obtenue en appliquant path_expression au motif de ligne, dans la ligne de sortie de la vue après l'avoir convertie au type spécifié.

La spécification de FORMAT JSON rend explicite le fait que vous attendez que la valeur soit un objet json valide. Il est uniquement pertinent de spécifier FORMAT JSON que si type est l'un des bpchar, bytea, character varying, name, json, jsonb, text, ou un domaine sur ces types.

En option, vous pouvez spécifier les clauses WRAPPER et QUOTES pour formater la sortie. Notez que la spécification de OMIT QUOTES remplace FORMAT JSON si elle est également spécifiée, car les litéraux non cités ne constituent pas des valeurs json valides.

En option, vous pouvez utiliser les clauses ON EMPTY et ON ERROR pour spécifier s'il faut remonter l'erreur ou renvoyer la valeur spécifiée lorsque le résultat de l'évaluation du chemin JSON est vide, et lorsqu'une erreur se produit pendant l'évaluation du chemin JSON ou lors de la conversion de la valeur SQL/JSON au type spécifié, respectivement. La valeur par défaut pour les deux est de renvoyer une valeur NULL.

Note

Cette clause est convertie en interne et a la même sémantique que JSON_VALUE ou JSON_QUERY. Ce sera JSON_QUERY si le type spécifié n'est pas un type scalaire ou si l'une des clauses FORMAT JSON, WRAPPER ou QUOTES est présente.

name type EXISTS [ PATH path_expression ]

Insère une valeur booléenne obtenue en appliquant path_expression au motif de ligne, dans la ligne en sortie de la vue après l'avoir convertie au type spécifié.

La valeur correspond à l'application de l'expression PATH au motif de ligne renvoyant des valeurs ou non.

Le type spécifié doit avoir une conversion à partir du type boolean.

En option, vous pouvez utiliser ON ERROR pour spécifier s'il faut remonter l'erreur ou renvoyer la valeur spécifiée lorsqu'une erreur se produit pendant l'évaluation du chemin JSON ou lors de la conversion de la valeur SQL/JSON au type spécifié. La valeur par défaut est de renvoyer une valeur booléenne FALSE.

Note

Cette clause est convertie en interne et, est sémantiquement équivalent à JSON_EXISTS.

NESTED [ PATH ] path_expression [ AS json_path_name ] COLUMNS ( json_table_column [, ...] )

Extrait des valeurs SQL/JSON des niveaux imbriqués du modèle de ligne, génère une ou plusieurs colonnes définies par la sous-clause COLUMNS, et insère les valeurs SQL/JSON ayant été extraites dans ces colonnes. L'expression json_table_column dans la sous-clause COLUMNS utilise la même syntaxe que dans la clause COLUMNS parente.

La syntaxe NESTED PATH est récursive, vous pouvez donc utiliser plusieurs niveaux imbriqués en spécifiant plusieurs sous-clauses NESTED PATH les unes dans les autres. Cela permet de décomposer la hiérarchie des objets et tableaux JSON en un seul appel de la fonction plutôt que de chaîner plusieurs expressions JSON_TABLE dans une instruction SQL.

Note

Dans chaque variante de json_table_column décrite ci-dessus, si la clause PATH est omise, l'expression de chemin $.name est utilisée, où name est le nom de colonne fourni.

AS json_path_name

Le json_path_name optionnel sert d'identifiant du path_expression fourni. Le nom doit être unique et distinct des noms de colonnes.

{ ERROR | EMPTY } ON ERROR

La clause optionnelle ON ERROR peut être utilisée pour spécifier comment gérer les erreurs lors de l'évaluation du path_expression de niveau supérieur. Utilisez ERROR si vous souhaitez que les erreurs se génèrent et EMPTY pour renvoyer une table vide, c'est-à-dire une table contenant 0 ligne. Notez que cette clause n'affecte pas les erreurs qui surviennent lors de l'évaluation des colonnes, pour lesquelles le comportement dépend de la spécification de la clause ON ERROR pour une colonne donnée.

Examples

Dans les exemples suivants, la table ci-dessous sera utilisée avec les données JSON indiquées :

CREATE TABLE my_films ( js jsonb );

INSERT INTO my_films VALUES (
'{ "favorites" : [
   { "kind" : "comedy", "films" : [
     { "title" : "Bananas",
       "director" : "Woody Allen"},
     { "title" : "The Dinner Game",
       "director" : "Francis Veber" } ] },
   { "kind" : "horror", "films" : [
     { "title" : "Psycho",
       "director" : "Alfred Hitchcock" } ] },
   { "kind" : "thriller", "films" : [
     { "title" : "Vertigo",
       "director" : "Alfred Hitchcock" } ] },
   { "kind" : "drama", "films" : [
     { "title" : "Yojimbo",
       "director" : "Akira Kurosawa" } ] }
  ] }');
   

La requête suivante montre comment utiliser JSON_TABLE pour transformer les objets JSON de la table my_films en une vue contenant des colonnes pour les clés kind, title et director contenues dans le JSON original ainsi qu'une colonne d'ordinalité :

SELECT jt.* FROM
 my_films,
 JSON_TABLE (js, '$.favorites[*]' COLUMNS (
   id FOR ORDINALITY,
   kind text PATH '$.kind',
   title text PATH '$.films[*].title' WITH WRAPPER,
   director text PATH '$.films[*].director' WITH WRAPPER)) AS jt;

 id |   kind   |             title              |             director
----+----------+--------------------------------+----------------------------------
  1 | comedy   | ["Bananas", "The Dinner Game"] | ["Woody Allen", "Francis Veber"]
  2 | horror   | ["Psycho"]                     | ["Alfred Hitchcock"]
  3 | thriller | ["Vertigo"]                    | ["Alfred Hitchcock"]
  4 | drama    | ["Yojimbo"]                    | ["Akira Kurosawa"]
(4 rows)

Voici une version modifiée de la requête ci-dessus pour montrer l'utilisation des arguments PASSING dans le filtre spécifié dans l'expression de chemin JSON de niveau supérieur ainsi que les différentes options pour les colonnes individuelles :

SELECT jt.* FROM
 my_films,
 JSON_TABLE (js, '$.favorites[*] ? (@.films[*].director == $filter)'
   PASSING 'Alfred Hitchcock' AS filter, 'Vertigo' AS filter2
     COLUMNS (
     id FOR ORDINALITY,
     kind text PATH '$.kind',
     title text FORMAT JSON PATH '$.films[*].title' OMIT QUOTES,
     director text PATH '$.films[*].director' KEEP QUOTES)) AS jt;

 id |   kind   |  title  |      director
----+----------+---------+--------------------
  1 | horror   | Psycho  | "Alfred Hitchcock"
  2 | thriller | Vertigo | "Alfred Hitchcock"
(2 rows)

Voici une version modifiée de la requête ci-dessus pour montrer l'utilisation de NESTED PATH pour remplir les colonnes title et director, illustrant comment elles sont jointes aux colonnes parents id et kind :

SELECT jt.* FROM
 my_films,
 JSON_TABLE ( js, '$.favorites[*] ? (@.films[*].director == $filter)'
   PASSING 'Alfred Hitchcock' AS filter
   COLUMNS (
    id FOR ORDINALITY,
    kind text PATH '$.kind',
    NESTED PATH '$.films[*]' COLUMNS (
      title text FORMAT JSON PATH '$.title' OMIT QUOTES,
      director text PATH '$.director' KEEP QUOTES))) AS jt;

 id |   kind   |  title  |      director
----+----------+---------+--------------------
  1 | horror   | Psycho  | "Alfred Hitchcock"
  2 | thriller | Vertigo | "Alfred Hitchcock"
(2 rows)

La prochaine est la même requête, mais cette fois ci, sans le filtre dans le chemin racine :

SELECT jt.* FROM
 my_films,
 JSON_TABLE ( js, '$.favorites[*]'
   COLUMNS (
    id FOR ORDINALITY,
    kind text PATH '$.kind',
    NESTED PATH '$.films[*]' COLUMNS (
      title text FORMAT JSON PATH '$.title' OMIT QUOTES,
      director text PATH '$.director' KEEP QUOTES))) AS jt;

 id |   kind   |      title      |      director
----+----------+-----------------+--------------------
  1 | comedy   | Bananas         | "Woody Allen"
  1 | comedy   | The Dinner Game | "Francis Veber"
  2 | horror   | Psycho          | "Alfred Hitchcock"
  3 | thriller | Vertigo         | "Alfred Hitchcock"
  4 | drama    | Yojimbo         | "Akira Kurosawa"
(5 rows)

Voici une autre requête utilisant un objet JSON différent comme entrée. Elle montre l'union "sibling join" (frères et sœurs) entre les chemins NESTED $.movies[*] et $.books[*] et également l'utilisation de la colonne FOR ORDINALITY aux niveaux NESTED (colonnes movie_id, book_id et author_id) :

SELECT * FROM JSON_TABLE (
'{"favorites":
    {"movies":
      [{"name": "One", "director": "John Doe"},
       {"name": "Two", "director": "Don Joe"}],
     "books":
      [{"name": "Mystery", "authors": [{"name": "Brown Dan"}]},
       {"name": "Wonder", "authors": [{"name": "Jun Murakami"}, {"name":"Craig Doe"}]}]
}}'::json, '$.favorites[*]'
COLUMNS (
  user_id FOR ORDINALITY,
  NESTED '$.movies[*]'
    COLUMNS (
    movie_id FOR ORDINALITY,
    mname text PATH '$.name',
    director text),
  NESTED '$.books[*]'
    COLUMNS (
      book_id FOR ORDINALITY,
      bname text PATH '$.name',
      NESTED '$.authors[*]'
        COLUMNS (
          author_id FOR ORDINALITY,
          author_name text PATH '$.name'))));

 user_id | movie_id | mname | director | book_id |  bname  | author_id | author_name
---------+----------+-------+----------+---------+---------+-----------+--------------
       1 |        1 | One   | John Doe |         |         |           |
       1 |        2 | Two   | Don Joe  |         |         |           |
       1 |          |       |          |       1 | Mystery |         1 | Brown Dan
       1 |          |       |          |       2 | Wonder  |         1 | Jun Murakami
       1 |          |       |          |       2 | Wonder  |         2 | Craig Doe
(5 rows)