mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
SQL/JSON: add standard JSON constructor functions
This commit introduces the SQL/JSON standard-conforming constructors for JSON types: JSON_ARRAY() JSON_ARRAYAGG() JSON_OBJECT() JSON_OBJECTAGG() Most of the functionality was already present in PostgreSQL-specific functions, but these include some new functionality such as the ability to skip or include NULL values, and to allow duplicate keys or throw error when they are found, as well as the standard specified syntax to specify output type and format. Author: Nikita Glukhov <n.gluhov@postgrespro.ru> Author: Teodor Sigaev <teodor@sigaev.ru> Author: Oleg Bartunov <obartunov@gmail.com> Author: Alexander Korotkov <aekorotkov@gmail.com> Author: Amit Langote <amitlangote09@gmail.com> Reviewers have included (in no particular order) Andres Freund, Alexander Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu, Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby. Discussion: https://postgr.es/m/CAF4Au4w2x-5LTnN_bxky-mq4=WOqsGsxSpENCzHRAzSnEd8+WQ@mail.gmail.com Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de Discussion: https://postgr.es/m/abd9b83b-aa66-f230-3d6d-734817f0995d%40postgresql.org
This commit is contained in:
@ -15229,6 +15229,10 @@ table2-mapping
|
||||
<primary>JSON</primary>
|
||||
<secondary>functions and operators</secondary>
|
||||
</indexterm>
|
||||
<indexterm zone="functions-json">
|
||||
<primary>SQL/JSON</primary>
|
||||
<secondary>functions and expressions</secondary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
This section describes:
|
||||
@ -15247,6 +15251,42 @@ table2-mapping
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To provide native support for JSON data types within the SQL environment,
|
||||
<productname>PostgreSQL</productname> implements the
|
||||
<firstterm>SQL/JSON data model</firstterm>.
|
||||
This model comprises sequences of items. Each item can hold SQL scalar
|
||||
values, with an additional SQL/JSON null value, and composite data structures
|
||||
that use JSON arrays and objects. The model is a formalization of the implied
|
||||
data model in the JSON specification
|
||||
<ulink url="https://tools.ietf.org/html/rfc7159">RFC 7159</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
SQL/JSON allows you to handle JSON data alongside regular SQL data,
|
||||
with transaction support, including:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Uploading JSON data into the database and storing it in
|
||||
regular SQL columns as character or binary strings.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Generating JSON objects and arrays from relational data.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Querying JSON data using SQL/JSON query functions and
|
||||
SQL/JSON path language expressions.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To learn more about the SQL/JSON standard, see
|
||||
<xref linkend="sqltr-19075-6"/>. For details on JSON types
|
||||
@ -15677,6 +15717,12 @@ table2-mapping
|
||||
<para>
|
||||
<xref linkend="functions-json-creation-table"/> shows the functions that are
|
||||
available for constructing <type>json</type> and <type>jsonb</type> values.
|
||||
Some functions in this table have a <literal>RETURNING</literal> clause,
|
||||
which specifies the data type returned. It must be one of <type>json</type>,
|
||||
<type>jsonb</type>, <type>bytea</type>, a character string type (<type>text</type>,
|
||||
<type>char</type>, <type>varchar</type>, or <type>nchar</type>), or a type
|
||||
for which there is a cast from <type>json</type> to that type.
|
||||
By default, the <type>json</type> type is returned.
|
||||
</para>
|
||||
|
||||
<table id="functions-json-creation-table">
|
||||
@ -15760,6 +15806,45 @@ table2-mapping
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<!--
|
||||
Note that this is barely legible in the output; it looks like a
|
||||
salad of braces and brackets. It would be better to split it out
|
||||
in multiple lines, but that's surprisingly hard to do in a way that
|
||||
matches in HTML and PDF output. Other standard SQL/JSON functions
|
||||
have the same problem.
|
||||
-->
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm><primary>json_array</primary></indexterm>
|
||||
<function>json_array</function> (
|
||||
<optional> { <replaceable>value_expression</replaceable> <optional> <literal>FORMAT JSON</literal> </optional> } <optional>, ...</optional> </optional>
|
||||
<optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
|
||||
<optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
|
||||
</para>
|
||||
<para role="func_signature">
|
||||
<function>json_array</function> (
|
||||
<optional> <replaceable>query_expression</replaceable> </optional>
|
||||
<optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
|
||||
</para>
|
||||
<para>
|
||||
Constructs a JSON array from either a series of
|
||||
<replaceable>value_expression</replaceable> parameters or from the results
|
||||
of <replaceable>query_expression</replaceable>,
|
||||
which must be a SELECT query returning a single column. If
|
||||
<literal>ABSENT ON NULL</literal> is specified, NULL values are ignored.
|
||||
This is always the case if a
|
||||
<replaceable>query_expression</replaceable> is used.
|
||||
</para>
|
||||
<para>
|
||||
<literal>json_array(1,true,json '{"a":null}')</literal>
|
||||
<returnvalue>[1, true, {"a":null}]</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
<literal>json_array(SELECT * FROM (VALUES(1),(2)) t)</literal>
|
||||
<returnvalue>[1, 2]</returnvalue>
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
@ -15833,6 +15918,38 @@ table2-mapping
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm><primary>json_object</primary></indexterm>
|
||||
<function>json_object</function> (
|
||||
<optional> { <replaceable>key_expression</replaceable> { <literal>VALUE</literal> | ':' }
|
||||
<replaceable>value_expression</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> }<optional>, ...</optional> </optional>
|
||||
<optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
|
||||
<optional> { <literal>WITH</literal> | <literal>WITHOUT</literal> } <literal>UNIQUE</literal> <optional> <literal>KEYS</literal> </optional> </optional>
|
||||
<optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
|
||||
</para>
|
||||
<para>
|
||||
Constructs a JSON object of all the key/value pairs given,
|
||||
or an empty object if none are given.
|
||||
<replaceable>key_expression</replaceable> is a scalar expression
|
||||
defining the <acronym>JSON</acronym> key, which is
|
||||
converted to the <type>text</type> type.
|
||||
It cannot be <literal>NULL</literal> nor can it
|
||||
belong to a type that has a cast to the <type>json</type> type.
|
||||
If <literal>WITH UNIQUE KEYS</literal> is specified, there must not
|
||||
be any duplicate <replaceable>key_expression</replaceable>.
|
||||
Any pair for which the <replaceable>value_expression</replaceable>
|
||||
evaluates to <literal>NULL</literal> is omitted from the output
|
||||
if <literal>ABSENT ON NULL</literal> is specified;
|
||||
if <literal>NULL ON NULL</literal> is specified or the clause
|
||||
omitted, the key is included with value <literal>NULL</literal>.
|
||||
</para>
|
||||
<para>
|
||||
<literal>json_object('code' VALUE 'P123', 'title': 'Jaws')</literal>
|
||||
<returnvalue>{"code" : "P123", "title" : "Jaws"}</returnvalue>
|
||||
</para></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
@ -20077,6 +20194,28 @@ SELECT NULLIF(value, '(none)') ...
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm><primary>json_objectagg</primary></indexterm>
|
||||
<function>json_objectagg</function> (
|
||||
<optional> { <replaceable>key_expression</replaceable> { <literal>VALUE</literal> | ':' } <replaceable>value_expression</replaceable> } </optional>
|
||||
<optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
|
||||
<optional> { <literal>WITH</literal> | <literal>WITHOUT</literal> } <literal>UNIQUE</literal> <optional> <literal>KEYS</literal> </optional> </optional>
|
||||
<optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
|
||||
</para>
|
||||
<para>
|
||||
Behaves like <function>json_object</function><!-- xref -->, but as an
|
||||
aggregate function, so it only takes one
|
||||
<replaceable>key_expression</replaceable> and one
|
||||
<replaceable>value_expression</replaceable> parameter.
|
||||
</para>
|
||||
<para>
|
||||
<literal>SELECT json_objectagg(k:v) FROM (VALUES ('a'::text,current_date),('b',current_date + 1)) AS t(k,v)</literal>
|
||||
<returnvalue>{ "a" : "2022-05-10", "b" : "2022-05-11" }</returnvalue>
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
@ -20098,9 +20237,122 @@ SELECT NULLIF(value, '(none)') ...
|
||||
</para>
|
||||
<para>
|
||||
Collects all the key/value pairs into a JSON object. Key arguments
|
||||
are coerced to text; value arguments are converted as
|
||||
per <function>to_json</function> or <function>to_jsonb</function>.
|
||||
Values can be null, but not keys.
|
||||
are coerced to text; value arguments are converted as per
|
||||
<function>to_json</function> or <function>to_jsonb</function>.
|
||||
Values can be null, but keys cannot.
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>json_object_agg_strict</primary>
|
||||
</indexterm>
|
||||
<function>json_object_agg_strict</function> (
|
||||
<parameter>key</parameter> <type>"any"</type>,
|
||||
<parameter>value</parameter> <type>"any"</type> )
|
||||
<returnvalue>json</returnvalue>
|
||||
</para>
|
||||
<para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>jsonb_object_agg_strict</primary>
|
||||
</indexterm>
|
||||
<function>jsonb_object_agg_strict</function> (
|
||||
<parameter>key</parameter> <type>"any"</type>,
|
||||
<parameter>value</parameter> <type>"any"</type> )
|
||||
<returnvalue>jsonb</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
Collects all the key/value pairs into a JSON object. Key arguments
|
||||
are coerced to text; value arguments are converted as per
|
||||
<function>to_json</function> or <function>to_jsonb</function>.
|
||||
The <parameter>key</parameter> can not be null. If the
|
||||
<parameter>value</parameter> is null then the entry is skipped,
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>json_object_agg_unique</primary>
|
||||
</indexterm>
|
||||
<function>json_object_agg_unique</function> (
|
||||
<parameter>key</parameter> <type>"any"</type>,
|
||||
<parameter>value</parameter> <type>"any"</type> )
|
||||
<returnvalue>json</returnvalue>
|
||||
</para>
|
||||
<para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>jsonb_object_agg_unique</primary>
|
||||
</indexterm>
|
||||
<function>jsonb_object_agg_unique</function> (
|
||||
<parameter>key</parameter> <type>"any"</type>,
|
||||
<parameter>value</parameter> <type>"any"</type> )
|
||||
<returnvalue>jsonb</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
Collects all the key/value pairs into a JSON object. Key arguments
|
||||
are coerced to text; value arguments are converted as per
|
||||
<function>to_json</function> or <function>to_jsonb</function>.
|
||||
Values can be null, but keys cannot.
|
||||
If there is a duplicate key an error is thrown.
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm><primary>json_arrayagg</primary></indexterm>
|
||||
<function>json_arrayagg</function> (
|
||||
<optional> <replaceable>value_expression</replaceable> </optional>
|
||||
<optional> <literal>ORDER BY</literal> <replaceable>sort_expression</replaceable> </optional>
|
||||
<optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
|
||||
<optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
|
||||
</para>
|
||||
<para>
|
||||
Behaves in the same way as <function>json_array</function>
|
||||
but as an aggregate function so it only takes one
|
||||
<replaceable>value_expression</replaceable> parameter.
|
||||
If <literal>ABSENT ON NULL</literal> is specified, any NULL
|
||||
values are omitted.
|
||||
If <literal>ORDER BY</literal> is specified, the elements will
|
||||
appear in the array in that order rather than in the input order.
|
||||
</para>
|
||||
<para>
|
||||
<literal>SELECT json_arrayagg(v) FROM (VALUES(2),(1)) t(v)</literal>
|
||||
<returnvalue>[2, 1]</returnvalue>
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>json_object_agg_unique_strict</primary>
|
||||
</indexterm>
|
||||
<function>json_object_agg_unique_strict</function> (
|
||||
<parameter>key</parameter> <type>"any"</type>,
|
||||
<parameter>value</parameter> <type>"any"</type> )
|
||||
<returnvalue>json</returnvalue>
|
||||
</para>
|
||||
<para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>jsonb_object_agg_unique_strict</primary>
|
||||
</indexterm>
|
||||
<function>jsonb_object_agg_unique_strict</function> (
|
||||
<parameter>key</parameter> <type>"any"</type>,
|
||||
<parameter>value</parameter> <type>"any"</type> )
|
||||
<returnvalue>jsonb</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
Collects all the key/value pairs into a JSON object. Key arguments
|
||||
are coerced to text; value arguments are converted as per
|
||||
<function>to_json</function> or <function>to_jsonb</function>.
|
||||
The <parameter>key</parameter> can not be null. If the
|
||||
<parameter>value</parameter> is null then the entry is skipped.
|
||||
If there is a duplicate key an error is thrown.
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
@ -20183,6 +20435,29 @@ SELECT NULLIF(value, '(none)') ...
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>json_agg_strict</primary>
|
||||
</indexterm>
|
||||
<function>json_agg_strict</function> ( <type>anyelement</type> )
|
||||
<returnvalue>json</returnvalue>
|
||||
</para>
|
||||
<para role="func_signature">
|
||||
<indexterm>
|
||||
<primary>jsonb_agg_strict</primary>
|
||||
</indexterm>
|
||||
<function>jsonb_agg_strict</function> ( <type>anyelement</type> )
|
||||
<returnvalue>jsonb</returnvalue>
|
||||
</para>
|
||||
<para>
|
||||
Collects all the input values, skipping nulls, into a JSON array.
|
||||
Values are converted to JSON as per <function>to_json</function>
|
||||
or <function>to_jsonb</function>.
|
||||
</para></entry>
|
||||
<entry>No</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry role="func_table_entry"><para role="func_signature">
|
||||
<indexterm>
|
||||
@ -20278,7 +20553,12 @@ SELECT NULLIF(value, '(none)') ...
|
||||
<para>
|
||||
The aggregate functions <function>array_agg</function>,
|
||||
<function>json_agg</function>, <function>jsonb_agg</function>,
|
||||
<function>json_agg_strict</function>, <function>jsonb_agg_strict</function>,
|
||||
<function>json_object_agg</function>, <function>jsonb_object_agg</function>,
|
||||
<function>json_object_agg_strict</function>, <function>jsonb_object_agg_strict</function>,
|
||||
<function>json_object_agg_unique</function>, <function>jsonb_object_agg_unique</function>,
|
||||
<function>json_object_agg_unique_strict</function>,
|
||||
<function>jsonb_object_agg_unique_strict</function>,
|
||||
<function>string_agg</function>,
|
||||
and <function>xmlagg</function>, as well as similar user-defined
|
||||
aggregate functions, produce meaningfully different result values
|
||||
|
Reference in New Issue
Block a user