aboutsummaryrefslogtreecommitdiff
path: root/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src')
-rw-r--r--doc/src/sgml/datatype.sgml37
-rw-r--r--doc/src/sgml/filelist.sgml1
-rw-r--r--doc/src/sgml/func.sgml500
-rw-r--r--doc/src/sgml/json.sgml413
4 files changed, 743 insertions, 208 deletions
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index ac285ce0119..cc458b4753f 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -139,7 +139,13 @@
<row>
<entry><type>json</type></entry>
<entry></entry>
- <entry>JSON data</entry>
+ <entry>textual JSON data</entry>
+ </row>
+
+ <row>
+ <entry><type>jsonb</type></entry>
+ <entry></entry>
+ <entry>binary JSON data, decomposed</entry>
</row>
<row>
@@ -4220,34 +4226,7 @@ SET xmloption TO { DOCUMENT | CONTENT };
</sect2>
</sect1>
- <sect1 id="datatype-json">
- <title><acronym>JSON</> Type</title>
-
- <indexterm zone="datatype-json">
- <primary>JSON</primary>
- </indexterm>
-
- <para>
- The <type>json</type> data type can be used to store JSON (JavaScript
- Object Notation) data, as specified in <ulink
- url="http://www.ietf.org/rfc/rfc4627.txt">RFC 4627</ulink>. Such
- data can also be stored as <type>text</type>, but the
- <type>json</type> data type has the advantage of checking that each
- stored value is a valid JSON value. There are also related support
- functions available; see <xref linkend="functions-json">.
- </para>
-
- <para>
- <productname>PostgreSQL</productname> allows only one server encoding
- per database. It is therefore not possible for JSON to conform rigidly
- to the specification unless the server encoding is UTF-8. Attempts to
- directly include characters which cannot be represented in the server
- encoding will fail; conversely, characters which can be represented in
- the server encoding but not in UTF-8 will be allowed.
- <literal>\uXXXX</literal> escapes are allowed regardless of the server
- encoding, and are checked only for syntactic correctness.
- </para>
- </sect1>
+ &json;
&array;
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 6c8e254a584..ab6fcf7838c 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -22,6 +22,7 @@
<!ENTITY dml SYSTEM "dml.sgml">
<!ENTITY func SYSTEM "func.sgml">
<!ENTITY indices SYSTEM "indices.sgml">
+<!ENTITY json SYSTEM "json.sgml">
<!ENTITY mvcc SYSTEM "mvcc.sgml">
<!ENTITY perform SYSTEM "perform.sgml">
<!ENTITY queries SYSTEM "queries.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 71b9829d852..4e2fff7cd74 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10079,12 +10079,13 @@ table2-mapping
</indexterm>
<para>
- <xref linkend="functions-json-op-table"> shows the operators that are
- available for use with JSON (see <xref linkend="datatype-json">) data.
+ <xref linkend="functions-json-op-table"> shows the operators that
+ are available for use with the two JSON datatypes (see <xref
+ linkend="datatype-json">).
</para>
<table id="functions-json-op-table">
- <title>JSON Operators</title>
+ <title><type>json</> and <type>jsonb</> Operators</title>
<tgroup cols="4">
<thead>
<row>
@@ -10121,13 +10122,13 @@ table2-mapping
</row>
<row>
<entry><literal>#&gt;</literal></entry>
- <entry>array of text</entry>
+ <entry>text[]</entry>
<entry>Get JSON object at specified path</entry>
<entry><literal>'{"a":[1,2,3],"b":[4,5,6]}'::json#&gt;'{a,2}'</literal></entry>
</row>
<row>
<entry><literal>#&gt;&gt;</literal></entry>
- <entry>array of text</entry>
+ <entry>text[]</entry>
<entry>Get JSON object at specified path as text</entry>
<entry><literal>'{"a":[1,2,3],"b":[4,5,6]}'::json#&gt;&gt;'{a,2}'</literal></entry>
</row>
@@ -10135,13 +10136,107 @@ table2-mapping
</tgroup>
</table>
+ <note>
+ <para>
+ There are parallel variants of these operators for both the
+ <type>json</type> and <type>jsonb</type> types. In addition to
+ those operators common to both types, a further set of operators
+ exists for <type>jsonb</type> (which comprise the default
+ <acronym>GIN</acronym> operator class).
+ </para>
+ </note>
<para>
- <xref linkend="functions-json-table"> shows the functions that are available
- for creating and manipulating JSON (see <xref linkend="datatype-json">) data.
+ The following are <type>jsonb</>-only operators, used by
+ <type>jsonb</> operator classes. For a full description of
+ <type>jsonb</> containment semantics and nesting, see <xref
+ linkend="json-containment">. <xref linkend="json-indexing">
+ describes how these operators can be used to effectively index
+ <type>jsonb</>.
</para>
+ <table id="functions-jsonb-op-table">
+ <title>Additonal JSONB Operators</title>
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Operator</entry>
+ <entry>Right Operand Type</entry>
+ <entry>Description</entry>
+ <entry>Example</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><literal>=</literal></entry>
+ <entry>jsonb</entry>
+ <entry>Is the jsonb equal to this jsonb?</entry>
+ <entry><literal>'[1,2,3]'::jsonb = '[1,2,3]'::jsonb</literal></entry>
+ </row>
+ <row>
+ <entry><literal>@&gt;</literal></entry>
+ <entry>jsonb</entry>
+ <entry>Does the jsonb contain within it this jsonb?</entry>
+ <entry><literal>'{"a":1, "b":2}'::jsonb &#64;&gt; '{"b":2}'::jsonb</literal></entry>
+ </row>
+ <row>
+ <entry><literal>&lt;@</literal></entry>
+ <entry>jsonb</entry>
+ <entry>Does the jsonb have contained within it this jsonb?</entry>
+ <entry><literal>'{"b":2}'::jsonb &lt;@ '{"a":1, "b":2}'::jsonb</literal></entry>
+ </row>
+ <row>
+ <entry><literal>?</literal></entry>
+ <entry>text</entry>
+ <entry>Does this key/element <emphasis>string</emphasis> exist?</entry>
+ <entry><literal>'{"a":1, "b":2}'::jsonb ? 'b'</literal></entry>
+ </row>
+ <row>
+ <entry><literal>?|</literal></entry>
+ <entry>text[]</entry>
+ <entry>Do any of these key/element <emphasis>strings</emphasis> exist?</entry>
+ <entry><literal>'{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c']</literal></entry>
+ </row>
+ <row>
+ <entry><literal>?&amp;</literal></entry>
+ <entry>text[]</entry>
+ <entry>Do all of these key/element <emphasis>strings</emphasis> exist?</entry>
+ <entry><literal>'["a", "b"]'::jsonb ?&amp; array['a', 'b']</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <!--
+ The release notes contain a reference to "functions-json-table". Since
+ that table is now split in two, the id has been parked here so we don't
+ have to change the release notes.
+ -->
+ <para id="functions-json-table">
+ <xref linkend="functions-json-creation-table"> shows the functions that are
+ available for creating <type>json</type> values.
+ (see <xref linkend="datatype-json">)
+ </para>
+
+ <indexterm>
+ <primary>array_to_json</primary>
+ </indexterm>
+ <indexterm>
+ <primary>row_to_json</primary>
+ </indexterm>
+ <indexterm>
+ <primary>to_json</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_build_array</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_build_object</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_object</primary>
+ </indexterm>
- <table id="functions-json-table">
- <title>JSON Support Functions</title>
+ <table id="functions-json-creation-table">
+ <title>JSON Creation Functions</title>
<tgroup cols="5">
<thead>
<row>
@@ -10155,9 +10250,6 @@ table2-mapping
<tbody>
<row>
<entry>
- <indexterm>
- <primary>array_to_json</primary>
- </indexterm>
<literal>array_to_json(anyarray [, pretty_bool])</literal>
</entry>
<entry><type>json</type></entry>
@@ -10171,9 +10263,6 @@ table2-mapping
</row>
<row>
<entry>
- <indexterm>
- <primary>row_to_json</primary>
- </indexterm>
<literal>row_to_json(record [, pretty_bool])</literal>
</entry>
<entry><type>json</type></entry>
@@ -10186,9 +10275,6 @@ table2-mapping
</row>
<row>
<entry>
- <indexterm>
- <primary>to_json</primary>
- </indexterm>
<literal>to_json(anyelement)</literal>
</entry>
<entry><type>json</type></entry>
@@ -10204,11 +10290,180 @@ table2-mapping
</row>
<row>
<entry>
- <indexterm>
- <primary>json_array_length</primary>
- </indexterm>
- <literal>json_array_length(json)</literal>
+ <literal>json_build_array(VARIADIC "any")</literal>
</entry>
+ <entry><type>json</type></entry>
+ <entry>
+ Builds a heterogeneously-typed json array out of a variadic argument list.
+ </entry>
+ <entry><literal>SELECT json_build_array(1,2,'3',4,5);</literal></entry>
+ <entry>
+<programlisting>
+ json_build_array
+-------------------
+ [1, 2, "3", 4, 5]
+ </programlisting>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>json_build_object(VARIADIC "any")</literal>
+ </entry>
+ <entry><type>json</type></entry>
+ <entry>
+ Builds a JSON array out of a variadic argument list. By
+ convention, the object is constructed out of alternating
+ name/value arguments.
+ </entry>
+ <entry><literal>SELECT json_build_object('foo',1,'bar',2);</literal></entry>
+ <entry>
+<programlisting>
+ json_build_object
+------------------------
+ {"foo" : 1, "bar" : 2}
+ </programlisting>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>json_object(text[])</literal>
+ </entry>
+ <entry><type>json</type></entry>
+ <entry>
+ Builds a JSON object out of a text array. The array must have either
+ exactly one dimension with an even number of members, in which case
+ they are taken as alternating name/value pairs, or two dimensions
+ such that each inner array has exactly two elements, which
+ are taken as a name/value pair.
+ </entry>
+ <entry><literal>select * from json_object('{a, 1, b, "def", c, 3.5}') or <literal>select json_object('{{a, 1},{b, "def"},{c, 3.5}}')</literal></literal></entry>
+ <entry>
+<programlisting>
+ json_object
+---------------------------------------
+ {"a" : "1", "b" : "def", "c" : "3.5"}
+ </programlisting>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>json_object(keys text[], values text[])</literal>
+ </entry>
+ <entry><type>json</type></entry>
+ <entry>
+ The two-argument form of JSON object takes keys and values pairwise from two separate
+ arrays. In all other respects it is identical to the one-argument form.
+ </entry>
+ <entry><literal>select json_object('{a, b}', '{1,2}');</literal></entry>
+ <entry>
+<programlisting>
+ json_object
+------------------------
+ {"a" : "1", "b" : "2"}
+ </programlisting>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+
+ <para>
+ <xref linkend="functions-json-processing-table"> shows the functions that
+ are available for processing <type>json</type> and <type>jsonb</type> values.
+ (see <xref linkend="datatype-json">)
+ </para>
+
+ <indexterm>
+ <primary>json_array_length</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_array_length</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_each</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_each</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_each_text</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_each_text</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_extract_path</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_extract_path</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_extract_path_text</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_extract_path_text</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_object_keys</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_object_keys</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_populate_record</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_populate_record</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_populate_recordset</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_populate_recordset</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_array_elements</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_array_elements</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_array_elements_text</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_array_elements_text</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_typeof</primary>
+ </indexterm>
+ <indexterm>
+ <primary>jsonb_typeof</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_to_record</primary>
+ </indexterm>
+ <indexterm>
+ <primary>json_to_recordset</primary>
+ </indexterm>
+
+ <table id="functions-json-processing-table">
+ <title>JSON Processing Functions</title>
+ <tgroup cols="5">
+ <thead>
+ <row>
+ <entry>Function</entry>
+ <entry>Return Type</entry>
+ <entry>Description</entry>
+ <entry>Example</entry>
+ <entry>Example Result</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><para><literal>json_array_length(json)</literal>
+ </para><para><literal>jsonb_array_length(jsonb)</literal>
+ </para></entry>
<entry><type>int</type></entry>
<entry>
Returns the number of elements in the outermost JSON array.
@@ -10217,13 +10472,12 @@ table2-mapping
<entry><literal>5</literal></entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_each</primary>
- </indexterm>
- <literal>json_each(json)</literal>
- </entry>
- <entry><type>SETOF key text, value json</type></entry>
+ <entry><para><literal>json_each(json)</literal>
+ </para><para><literal>jsonb_each(jsonb)</literal>
+ </para></entry>
+ <entry><para><literal>SETOF key text, value json</literal>
+ </para><para><literal>SETOF key text, value jsonb</literal>
+ </para></entry>
<entry>
Expands the outermost JSON object into a set of key/value pairs.
</entry>
@@ -10238,12 +10492,9 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_each_text</primary>
- </indexterm>
- <literal>json_each_text(from_json json)</literal>
- </entry>
+ <entry><para><literal>json_each_text(from_json json)</literal>
+ </para><para><literal>jsonb_each_text(from_json jsonb)</literal>
+ </para></entry>
<entry><type>SETOF key text, value text</type></entry>
<entry>
Expands the outermost JSON object into a set of key/value pairs. The
@@ -10260,13 +10511,11 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_extract_path</primary>
- </indexterm>
- <literal>json_extract_path(from_json json, VARIADIC path_elems text[])</literal>
- </entry>
- <entry><type>json</type></entry>
+ <entry><para><literal>json_extract_path(from_json json, VARIADIC path_elems text[])</literal>
+ </para><para><literal>jsonb_extract_path(from_jsonb jsonb, VARIADIC path_elems text[])</literal>
+ </para></entry>
+ <entry><para><type>json</type></para><para><type>jsonb</type>
+ </para></entry>
<entry>
Returns JSON value pointed to by <parameter>path_elems</parameter>.
</entry>
@@ -10274,12 +10523,9 @@ table2-mapping
<entry><literal>{"f5":99,"f6":"foo"}</literal></entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_extract_path_text</primary>
- </indexterm>
- <literal>json_extract_path_text(from_json json, VARIADIC path_elems text[])</literal>
- </entry>
+ <entry><para><literal>json_extract_path_text(from_json json, VARIADIC path_elems text[])</literal>
+ </para><para><literal>json_extract_path_text(from_json json, VARIADIC path_elems text[])</literal>
+ </para></entry>
<entry><type>text</type></entry>
<entry>
Returns JSON value pointed to by <parameter>path_elems</parameter>.
@@ -10288,12 +10534,9 @@ table2-mapping
<entry><literal>foo</literal></entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_object_keys</primary>
- </indexterm>
- <literal>json_object_keys(json)</literal>
- </entry>
+ <entry><para><literal>json_object_keys(json)</literal>
+ </para><para><literal>jsonb_object_keys(jsonb)</literal>
+ </para></entry>
<entry><type>SETOF text</type></entry>
<entry>
Returns set of keys in the JSON object. Only the <quote>outer</quote> object will be displayed.
@@ -10309,18 +10552,16 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_populate_record</primary>
- </indexterm>
- <literal>json_populate_record(base anyelement, from_json json, [, use_json_as_text bool=false]</literal>
- </entry>
+ <entry><para><literal>json_populate_record(base anyelement, from_json json, [, use_json_as_text bool=false])</literal>
+ </para><para><literal>jsonb_populate_record(base anyelement, from_json jsonb, [, use_json_as_text bool=false])</literal>
+ </para></entry>
<entry><type>anyelement</type></entry>
<entry>
Expands the object in <replaceable>from_json</replaceable> to a row whose columns match
the record type defined by base. Conversion will be best
effort; columns in base with no corresponding key in <replaceable>from_json</replaceable>
- will be left null. If a column is specified more than once, the last value is used.
+ will be left null. When processing <type>json</type>, if a
+ column is specified more than once, the last value is used.
</entry>
<entry><literal>select * from json_populate_record(null::x, '{"a":1,"b":2}')</literal></entry>
<entry>
@@ -10332,19 +10573,17 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_populate_recordset</primary>
- </indexterm>
- <literal>json_populate_recordset(base anyelement, from_json json, [, use_json_as_text bool=false]</literal>
- </entry>
+ <entry><para><literal>json_populate_recordset(base anyelement, from_json json, [, use_json_as_text bool=false])</literal>
+ </para><para><literal>jsonb_populate_recordset(base anyelement, from_json jsonb, [, use_json_as_text bool=false])</literal>
+ </para></entry>
<entry><type>SETOF anyelement</type></entry>
<entry>
Expands the outermost set of objects in <replaceable>from_json</replaceable> to a set
whose columns match the record type defined by base.
Conversion will be best effort; columns in base with no
corresponding key in <replaceable>from_json</replaceable> will be left null.
- If a column is specified more than once, the last value is used.
+ When processing <type>json</type>, if a column is specified more
+ than once, the last value is used.
</entry>
<entry><literal>select * from json_populate_recordset(null::x, '[{"a":1,"b":2},{"a":3,"b":4}]')</literal></entry>
<entry>
@@ -10357,13 +10596,12 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_array_elements</primary>
- </indexterm>
- <literal>json_array_elements(json)</literal>
- </entry>
- <entry><type>SETOF json</type></entry>
+ <entry><para><literal>json_array_elements(json)</literal>
+ </para><para><literal>jsonb_array_elements(jsonb)</literal>
+ </para></entry>
+ <entry><para><type>SETOF json</type>
+ </para><para><type>SETOF jsonb</type>
+ </para></entry>
<entry>
Expands a JSON array to a set of JSON values.
</entry>
@@ -10379,12 +10617,9 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_array_elements_text</primary>
- </indexterm>
- <literal>json_array_elements_text(json)</literal>
- </entry>
+ <entry><para><literal>json_array_elements_text(json)</literal>
+ </para><para><literal>jsonb_array_elements_text(jsonb)</literal>
+ </para></entry>
<entry><type>SETOF text</type></entry>
<entry>
Expands a JSON array to a set of text values.
@@ -10400,12 +10635,9 @@ table2-mapping
</entry>
</row>
<row>
- <entry>
- <indexterm>
- <primary>json_typeof</primary>
- </indexterm>
- <literal>json_typeof(json)</literal>
- </entry>
+ <entry><para><literal>json_typeof(json)</literal>
+ </para><para><literal>jsonb_typeof(jsonb)</literal>
+ </para></entry>
<entry><type>text</type></entry>
<entry>
Returns the type of the outermost JSON value as a text string. The types are
@@ -10418,98 +10650,11 @@ table2-mapping
</row>
<row>
<entry>
- <indexterm>
- <primary>json_build_array</primary>
- </indexterm>
- <literal>json_build_array(VARIADIC "any")</literal>
- </entry>
- <entry><type>json</type></entry>
- <entry>
- Builds a heterogeneously-typed json array out of a variadic argument list.
- </entry>
- <entry><literal>SELECT json_build_array(1,2,'3',4,5);</literal></entry>
- <entry>
-<programlisting>
- json_build_array
--------------------
- [1, 2, "3", 4, 5]
- </programlisting>
- </entry>
- </row>
- <row>
- <entry>
- <indexterm>
- <primary>json_build_object</primary>
- </indexterm>
- <literal>json_build_object(VARIADIC "any")</literal>
- </entry>
- <entry><type>json</type></entry>
- <entry>
- Builds a JSON array out of a variadic argument list.
- By convention, the object is
- constructed out of alternating name/value arguments.
- </entry>
- <entry><literal>SELECT json_build_object('foo',1,'bar',2);</literal></entry>
- <entry>
-<programlisting>
- json_build_object
-------------------------
- {"foo" : 1, "bar" : 2}
- </programlisting>
- </entry>
- </row>
- <row>
- <entry>
- <indexterm>
- <primary>json_object</primary>
- </indexterm>
- <literal>json_object(text[])</literal>
- </entry>
- <entry><type>json</type></entry>
- <entry>
- Builds a JSON object out of a text array. The array must have either
- exactly one dimension with an even number of members, in which case
- they are taken as alternating name/value pairs, or two dimensions
- such that each inner array has exactly two elements, which
- are taken as a name/value pair.
- </entry>
- <entry><literal>select * from json_object('{a, 1, b, "def", c, 3.5}') or <literal>select * from json_object('{{a, 1},{b, "def"},{c, 3.5}}')</literal></literal></entry>
- <entry>
-<programlisting>
- json_object
----------------------------------------
- {"a" : "1", "b" : "def", "c" : "3.5"}
- </programlisting>
- </entry>
- </row>
- <row>
- <entry>
- <literal>json_object(keys text[], values text[])</literal>
- </entry>
- <entry><type>json</type></entry>
- <entry>
- The two-argument form of JSON object takes keys and values pairwise from two separate
- arrays. In all other respects it is identical to the one-argument form.
- </entry>
- <entry><literal>select * from json_object('{a, b}', '{1,2}');</literal></entry>
- <entry>
-<programlisting>
- json_object
-------------------------
- {"a" : "1", "b" : "2"}
- </programlisting>
- </entry>
- </row>
- <row>
- <entry>
- <indexterm>
- <primary>json_to_record</primary>
- </indexterm>
<literal>json_to_record(json, nested_as_text bool)</literal>
</entry>
<entry><type>record</type></entry>
<entry>
- json_to_record returns an arbitrary record from a JSON object. As with all functions
+ Returns an arbitrary record from a JSON object. As with all functions
returning 'record', the caller must explicitly define the structure of the record
when making the call. The input JSON must be an object, not a scalar or an array.
If nested_as_text is true, the function coerces nested complex elements to text.
@@ -10526,14 +10671,11 @@ table2-mapping
</row>
<row>
<entry>
- <indexterm>
- <primary>json_to_recordset</primary>
- </indexterm>
<literal>json_to_recordset(json, nested_as_text bool)</literal>
</entry>
<entry><type>setof record</type></entry>
<entry>
- json_to_recordset returns an arbitrary set of records from a JSON object. As with
+ Returns an arbitrary set of records from a JSON object. As with
json_to_record, the structure of the record must be explicitly defined when making the
call. However, with json_to_recordset the input JSON must be an array containing
objects. nested_as_text works as with json_to_record.
diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml
new file mode 100644
index 00000000000..d7d6de8d287
--- /dev/null
+++ b/doc/src/sgml/json.sgml
@@ -0,0 +1,413 @@
+<!-- doc/src/sgml/json.sgml -->
+
+<sect1 id="datatype-json">
+ <title><acronym>JSON</> Types</title>
+
+ <indexterm zone="datatype-json">
+ <primary>JSON</primary>
+ </indexterm>
+
+ <indexterm zone="datatype-json">
+ <primary>JSONB</primary>
+ </indexterm>
+
+ <para>
+ JSON data types are for storing JSON (JavaScript Object Notation)
+ data, as specified in <ulink url="http://rfc7159.net/rfc7159">RFC
+ 7159</ulink>. Such data can also be stored as <type>text</type>, but
+ both JSON data types have the advantage of enforcing that each
+ stored value is a valid JSON value. There are also related support
+ functions available; see <xref linkend="functions-json">.
+ </para>
+
+ <para>
+ There are two JSON data types: <type>json</> and <type>jsonb</>.
+ Both accept <emphasis>almost</emphasis> identical sets of values as
+ input. The major practical difference is one of efficiency. The
+ <type>json</> data type stores an exact copy of the the input text,
+ which processing functions must continually reparse, while
+ <type>jsonb</> data is stored in a decomposed binary format that
+ makes it slightly less efficient to input due to added serialization
+ overhead, but significantly faster to process, since it never needs
+ reparsing. <type>jsonb</> also supports advanced
+ <acronym>GIN</acronym> indexing, which is a further significant
+ advantage.
+ </para>
+
+ <para>
+ The other difference between the types is that the <type>json</>
+ type is guaranteed to contain an exact copy of the input, including
+ preservation of semantically insignificant white space, and the
+ order of keys within JSON objects (although <type>jsonb</> will
+ preserve trailing zeros within a JSON number). Also, because the
+ exact text is kept, if a JSON object within the value contains the
+ same key more than once, and has been stored using the <type>json</>
+ type, all the key/value pairs are kept. In that case, the
+ processing functions consider the last value as the operative one.
+ By contrast, <type>jsonb</> does not preserve white space, does not
+ preserve the order of object keys, and does not keep duplicate
+ object keys. Only the last value for a key specified in the input
+ is kept.
+ </para>
+
+ <para>
+ In general, most applications will prefer to store JSON data as
+ <type>jsonb</>, unless there are quite specialized needs.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> allows only one server
+ encoding per database. It is therefore not possible for the JSON
+ types to conform rigidly to the specification unless the server
+ encoding is UTF-8. Attempts to directly include characters which
+ cannot be represented in the server encoding will fail; conversely,
+ characters which can be represented in the server encoding but not
+ in UTF-8 will be allowed. <literal>\uXXXX</literal> escapes are
+ allowed regardless of the server encoding, and are checked only for
+ syntactic correctness.
+ </para>
+
+ <sect2 id="json-types">
+ <title>Mapping of RFC-7159/JSON Primitive Types to <productname>PostgreSQL</productname> Types</title>
+ <table id="json-type-mapping-table">
+ <title>Mapping of type correspondence, notes</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry><productname>PostgreSQL</productname> type</entry>
+ <entry>RFC-7159/JSON primitive type</entry>
+ <entry>Notes</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry><type>text</></entry>
+ <entry><type>string</></entry>
+ <entry>See general introductory notes on encoding and JSON</entry>
+ </row>
+ <row>
+ <entry><type>numeric</></entry>
+ <entry><type>number</></entry>
+ <entry><literal>NaN</literal> and <literal>infinity</literal> values are disallowed</entry>
+ </row>
+ <row>
+ <entry><type>boolean</></entry>
+ <entry><type>boolean</></entry>
+ <entry>Only lowercase <literal>true</literal> and <literal>false</literal> values are accepted</entry>
+ </row>
+ <row>
+ <entry><type>unknown</></entry>
+ <entry><type>null</></entry>
+ <entry>SQL <literal>NULL</literal> is orthogonal. NULL semantics do not apply.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ Primitive types described by <acronym>RFC</> 7159 are effectively
+ internally mapped onto native
+ <productname>PostgreSQL</productname> types. Therefore, there are
+ some very minor additional constraints on what constitutes valid
+ <type>jsonb</type> that do not apply to the <type>json</type>
+ type, or to JSON in the abstract, that pertain to limits on what
+ can be represented by the underlying type system. These
+ implementation-defined restrictions are permitted by
+ <acronym>RFC</> 7159. However, in practice problems are far more
+ likely to occur in other implementations which internally
+ represent the <type>number</> JSON primitive type as IEEE 754
+ double precision floating point values, which <acronym>RFC</> 7159
+ explicitly anticipates and allows for. When using JSON as an
+ interchange format with such systems, the danger of losing numeric
+ precision in respect of data originally stored by
+ <productname>PostgreSQL</productname> should be considered.
+ </para>
+ <para>
+ Conversely, as noted above there are some minor restrictions on
+ the input format of JSON primitive types that do not apply to
+ corresponding <productname>PostgreSQL</productname> types.
+ </para>
+
+ </sect2>
+
+ <sect2 id="json-querying">
+ <title>Querying <type>jsonb</type> documents effectively</title>
+ <para>
+ Representing data as JSON can be considerably more flexible than
+ the traditional relational data model, which is compelling in
+ environments where requirements are fluid. It is quite possible
+ for both approaches to co-exist and complement each other within
+ the same application. However, even for applications where maximal
+ flexibility is desired, it is still recommended that JSON documents
+ have a somewhat fixed structure. This structure is typically
+ unenforced (though enforcing some business rules declaratively is
+ possible), but makes it easier to write queries that usefully
+ summarize a set of <quote>documents</> (datums) in a table.
+ </para>
+ <para>
+ <type>jsonb</> data is subject to the same concurrency control
+ considerations as any other datatype when stored in a table.
+ Although storing large documents is practicable, in order to ensure
+ correct behavior row-level locks are, quite naturally, aquired as
+ rows are updated. Consider keeping <type>jsonb</> documents at a
+ manageable size in order to decrease lock contention among updating
+ transactions. Ideally, <type>jsonb</> documents should each
+ represent an atomic datum that business rules dictate cannot
+ reasonably be further subdivided into smaller atomic datums that
+ can be independently modified.
+ </para>
+ </sect2>
+ <sect2 id="json-keys-elements">
+ <title><type>jsonb</> Input and Output Syntax</title>
+ <para>
+ In effect, <type>jsonb</> has an internal type system whose
+ implementation is defined in terms of several particular ordinary
+ <productname>PostgreSQL</productname> types. The SQL parser does
+ not have direct knowledge of the internal types that constitute a
+ <type>jsonb</>.
+ </para>
+ <para>
+ The following are all valid <type>jsonb</> expressions:
+ <programlisting>
+-- Simple scalar/primitive value (explicitly required by RFC-7159)
+SELECT '5'::jsonb;
+
+-- Array of heterogeneous, primitive-typed elements
+SELECT '[1, 2, "foo", null]'::jsonb;
+
+-- Object of heterogeneous key/value pairs of primitive types
+-- Note that key values are always strings
+SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
+ </programlisting>
+ </para>
+ <para>
+ Note the distinction between scalar/primitive values as elements,
+ keys and values.
+ </para>
+ </sect2>
+ <sect2 id="json-containment">
+ <title><type>jsonb</> containment</title>
+ <indexterm>
+ <primary>jsonb</primary>
+ <secondary>containment</secondary>
+ </indexterm>
+ <para>
+ Testing <quote>containment</> is an important capability of
+ <type>jsonb</>. There is no parallel set of facilities for the
+ <type>json</> type. Containment is the ability to determine if
+ one <type>jsonb</> document has contained within it another one.
+ <type>jsonb</> is nested, and so containment semantics are nested;
+ technically, top-down, unordered <emphasis>subtree isomorphism</>
+ may be tested. Containment is conventionally tested using the
+ <literal>@&gt;</> operator, which is made indexable by various
+ operator classes discussed later in this section.
+ </para>
+ <programlisting>
+-- Simple scalar/primitive values may contain only each other:
+SELECT '"foo"'::jsonb @> '"foo"'::jsonb;
+
+-- The array on the right hand side is contained within the one on the
+-- left hand side:
+SELECT '[1, 2, 3]'::jsonb @> '[1, 3]'::jsonb;
+
+-- The object with a single pair on the right hand side is contained
+-- within the object on the left hand side:
+SELECT '{"product": "PostgreSQL", "version": 9.4, "jsonb":true}'::jsonb @> '{"version":9.4}'::jsonb;
+
+-- The array on the right hand side is not contained within the array
+-- containing a nested array on the left hand side:
+SELECT '[1, 2, [1, 3]]'::jsonb @> '[1, 3]'::jsonb;
+
+-- But with a layer of nesting, it is:
+SELECT '[1, 2, [1, 3]]'::jsonb @> '[[1, 3]]'::jsonb;
+ </programlisting>
+ <para>
+ It is both a sufficient and a necessary condition for nesting
+ levels to <quote>line up</> for one <type>jsonb</> to contain
+ within it another. Under this definition, objects and arrays
+ cannot <quote>line up</>, not least because objects contain
+ key/value pairs, while arrays contain elements.
+ </para>
+ <para>
+ As a special exception to the general principle that nesting
+ levels should <quote>line up</>, an array may contain a raw scalar:
+ </para>
+ <programlisting>
+-- This array contains the raw scalar value:
+SELECT '["foo", "bar"]'::jsonb @> '"bar"'::jsonb;
+-- The special exception is not reciprocated -- non-containment is indicated here:
+SELECT '"bar"'::jsonb @> '["bar"]'::jsonb;
+ </programlisting>
+ <para>
+ Objects are better suited for testing containment when there is a
+ great deal of nesting involved, because unlike arrays they are
+ internally optimized for searching, and do not need to be searched
+ linearly within a single <type>jsonb</> document.
+ </para>
+ <programlisting>
+-- The right-hand side object is contained in this example:
+SELECT '{"p":1, "a":{"b":3, "q":11}, "i":77}'::jsonb @> '{"a":{"b":3}}'::jsonb;
+ </programlisting>
+ <para>
+ The various containment operators, along with all other JSON
+ operators and support functions are documented fully within <xref
+ linkend="functions-json">, <xref
+ linkend="functions-jsonb-op-table">.
+ </para>
+ </sect2>
+ <sect2 id="json-indexing">
+ <title><type>jsonb</> GIN Indexing</title>
+ <indexterm>
+ <primary>jsonb</primary>
+ <secondary>indexes on</secondary>
+ </indexterm>
+ <para>
+ <type>jsonb</> GIN indexes can be used to efficiently search among
+ more than one possible key/value pair within a single
+ <type>jsonb</> datum/document, among a large number of such
+ documents within a column in a table (i.e. among many rows).
+ </para>
+ <para>
+ <type>jsonb</> has GIN index support for the <literal>@&gt;</>,
+ <literal>?</>, <literal>?&amp;</> and <literal>?|</> operators.
+ The default GIN operator class makes all these operators
+ indexable:
+ </para>
+ <programlisting>
+-- GIN index (default opclass)
+CREATE INDEX idxgin ON api USING GIN (jdoc);
+
+-- GIN jsonb_hash_ops index
+CREATE INDEX idxginh ON api USING GIN (jdoc jsonb_hash_ops);
+ </programlisting>
+ <para>
+ The non-default GIN operator class <literal>jsonb_hash_ops</>
+ supports indexing the <literal>@&gt;</> operator only.
+ </para>
+ <para>
+ Consider the example of a table that stores JSON documents
+ retrieved from a third-party web service, with a documented schema
+ definition. An example of a document retrieved from this web
+ service is as follows:
+ <programlisting>
+{
+ "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
+ "name": "Angela Barton",
+ "is_active": true,
+ "company": "Magnafone",
+ "address": "178 Howard Place, Gulf, Washington, 702",
+ "registered": "2009-11-07T08:53:22 +08:00",
+ "latitude": 19.793713,
+ "longitude": 86.513373,
+ "tags": [
+ "enim",
+ "aliquip",
+ "qui"
+ ]
+}
+ </programlisting>
+ If a GIN index is created on the table that stores these
+ documents, <literal>api</literal>, on its <literal>jdoc</>
+ <type>jsonb</> column, we can expect that queries like the
+ following may make use of the index:
+ <programlisting>
+-- Note that both key and value have been specified
+SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @&gt; '{"company": "Magnafone"}';
+ </programlisting>
+ However, the index could not be used for queries like the
+ following, due to the aforementioned nesting restriction:
+ <programlisting>
+SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc -> 'tags' ? 'qui';
+ </programlisting>
+ Still, with judicious use of expressional indexing, the above
+ query can use an index scan. If there is a requirement to find
+ those records with a particular tag quickly, and the tags have a
+ high cardinality across all documents, defining an index as
+ follows is an effective approach to indexing:
+ <programlisting>
+-- Note that the "jsonb -> text" operator can only be called on an
+-- object, so as a consequence of creating this index the root "jdoc"
+-- datum must be an object. This is enforced during insertion.
+CREATE INDEX idxgin ON api USING GIN ((jdoc -> 'tags'));
+ </programlisting>
+ </para>
+ <para>
+ Expressional indexes are discussed in <xref
+ linkend="indexes-expressional">.
+ </para>
+ <para>
+ For the most flexible approach in terms of what may be indexed,
+ sophisticated querying on nested structures is possible by
+ exploiting containment. At the cost of having to create an index
+ on the entire structure for each row, and not just a nested
+ subset, we may exploit containment semantics to get an equivalent
+ result with a non-expressional index on the entire <quote>jdoc</>
+ column, <emphasis>without</> ever having to create additional
+ expressional indexes against the document (provided only
+ containment will be tested). While the index will be considerably
+ larger than our expression index, it will also be much more
+ flexible, allowing arbitrary structured searching. Such an index
+ can generally be expected to help with a query like the following:
+ </para>
+ <programlisting>
+SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @&gt; '{"tags": ["qui"]}';
+ </programlisting>
+ <para>
+ For full details of the semantics that these indexable operators
+ implement, see <xref linkend="functions-json">, <xref
+ linkend="functions-jsonb-op-table">.
+ </para>
+ </sect2>
+ <sect2 id="json-opclass">
+ <title><type>jsonb</> non-default GIN operator class</title>
+ <indexterm>
+ <primary>jsonb</primary>
+ <secondary>indexes on</secondary>
+ </indexterm>
+ <para>
+ Although only the <literal>@&gt;</> operator is made indexable, a
+ <literal>jsonb_hash_ops</literal> operator class GIN index has
+ some notable advantages over an equivalent GIN index of the
+ default GIN operator class for <type>jsonb</type>. Search
+ operations typically perform considerably better, and the on-disk
+ size of a <literal>jsonb_hash_ops</literal> operator class GIN
+ index can be much smaller.
+ </para>
+ </sect2>
+ <sect2 id="json-btree-indexing">
+ <title><type>jsonb</> B-Tree and hash indexing</title>
+ <para>
+ <type>jsonb</type> comparisons and related operations are
+ <emphasis>type-wise</>, in that the underlying
+ <productname>PostgreSQL</productname> datatype comparators are
+ invoked recursively, much like a traditional composite type.
+ </para>
+ <para>
+ <type>jsonb</> also supports <type>btree</> and <type>hash</>
+ indexes. Ordering between <type>jsonb</> datums is:
+ <synopsis>
+ <replaceable>Object</replaceable> > <replaceable>Array</replaceable> > <replaceable>Boolean</replaceable> > <replaceable>Number</replaceable> > <replaceable>String</replaceable> > <replaceable>Null</replaceable>
+
+ <replaceable>Object with n pairs</replaceable> > <replaceable>object with n - 1 pairs</replaceable>
+
+ <replaceable>Array with n elements</replaceable> > <replaceable>array with n - 1 elements</replaceable>
+ </synopsis>
+ Subsequently, individual primitive type comparators are invoked.
+ All comparisons of JSON primitive types occurs using the same
+ comparison rules as the underlying
+ <productname>PostgreSQL</productname> types. Strings are
+ compared lexically, using the default database collation.
+ Objects with equal numbers of pairs are compared:
+ <synopsis>
+ <replaceable>key-1</replaceable>, <replaceable>value-1</replaceable>, <replaceable>key-2</replaceable> ...
+ </synopsis>
+ Note however that object keys are compared in their storage order, and in particular,
+ since shorter keys are stored before longer keys, this can lead to results that might be
+ unintuitive, such as:
+ <programlisting>{ "aa": 1, "c": 1} > {"b": 1, "d": 1}</programlisting>
+ Similarly, arrays with equal numbers of elements are compared:
+ <synopsis>
+ <replaceable>element-1</replaceable>, <replaceable>element-2</replaceable> ...
+ </synopsis>
+ </para>
+ </sect2>
+</sect1>