-- Strings. SELECT '""'::jsonb; -- OK. jsonb ------- "" (1 row) SELECT $$''$$::jsonb; -- ERROR, single quotes are not allowed ERROR: invalid input syntax for type json LINE 1: SELECT $$''$$::jsonb; ^ DETAIL: Token "'" is invalid. CONTEXT: JSON data, line 1: '... SELECT '"abc"'::jsonb; -- OK jsonb ------- "abc" (1 row) SELECT '"abc'::jsonb; -- ERROR, quotes not closed ERROR: invalid input syntax for type json LINE 1: SELECT '"abc'::jsonb; ^ DETAIL: Token ""abc" is invalid. CONTEXT: JSON data, line 1: "abc SELECT '"abc def"'::jsonb; -- ERROR, unescaped newline in string constant ERROR: invalid input syntax for type json LINE 1: SELECT '"abc ^ DETAIL: Character with value 0x0a must be escaped. CONTEXT: JSON data, line 1: "abc SELECT '"\n\"\\"'::jsonb; -- OK, legal escapes jsonb ---------- "\n\"\\" (1 row) SELECT '"\v"'::jsonb; -- ERROR, not a valid JSON escape ERROR: invalid input syntax for type json LINE 1: SELECT '"\v"'::jsonb; ^ DETAIL: Escape sequence "\v" is invalid. CONTEXT: JSON data, line 1: "\v... SELECT '"\u"'::jsonb; -- ERROR, incomplete escape ERROR: invalid input syntax for type json LINE 1: SELECT '"\u"'::jsonb; ^ DETAIL: "\u" must be followed by four hexadecimal digits. CONTEXT: JSON data, line 1: "\u" SELECT '"\u00"'::jsonb; -- ERROR, incomplete escape ERROR: invalid input syntax for type json LINE 1: SELECT '"\u00"'::jsonb; ^ DETAIL: "\u" must be followed by four hexadecimal digits. CONTEXT: JSON data, line 1: "\u00" SELECT '"\u000g"'::jsonb; -- ERROR, g is not a hex digit ERROR: invalid input syntax for type json LINE 1: SELECT '"\u000g"'::jsonb; ^ DETAIL: "\u" must be followed by four hexadecimal digits. CONTEXT: JSON data, line 1: "\u000g... SELECT '"\u0000"'::jsonb; -- OK, legal escape jsonb ----------- "\\u0000" (1 row) -- use octet_length here so we don't get an odd unicode char in the -- output SELECT octet_length('"\uaBcD"'::jsonb::text); -- OK, uppercase and lower case both OK octet_length -------------- 5 (1 row) -- Numbers. SELECT '1'::jsonb; -- OK jsonb ------- 1 (1 row) SELECT '0'::jsonb; -- OK jsonb ------- 0 (1 row) SELECT '01'::jsonb; -- ERROR, not valid according to JSON spec ERROR: invalid input syntax for type json LINE 1: SELECT '01'::jsonb; ^ DETAIL: Token "01" is invalid. CONTEXT: JSON data, line 1: 01 SELECT '0.1'::jsonb; -- OK jsonb ------- 0.1 (1 row) SELECT '9223372036854775808'::jsonb; -- OK, even though it's too large for int8 jsonb --------------------- 9223372036854775808 (1 row) SELECT '1e100'::jsonb; -- OK jsonb ------------------------------------------------------------------------------------------------------- 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (1 row) SELECT '1.3e100'::jsonb; -- OK jsonb ------------------------------------------------------------------------------------------------------- 13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (1 row) SELECT '1f2'::jsonb; -- ERROR ERROR: invalid input syntax for type json LINE 1: SELECT '1f2'::jsonb; ^ DETAIL: Token "1f2" is invalid. CONTEXT: JSON data, line 1: 1f2 SELECT '0.x1'::jsonb; -- ERROR ERROR: invalid input syntax for type json LINE 1: SELECT '0.x1'::jsonb; ^ DETAIL: Token "0.x1" is invalid. CONTEXT: JSON data, line 1: 0.x1 SELECT '1.3ex100'::jsonb; -- ERROR ERROR: invalid input syntax for type json LINE 1: SELECT '1.3ex100'::jsonb; ^ DETAIL: Token "1.3ex100" is invalid. CONTEXT: JSON data, line 1: 1.3ex100 -- Arrays. SELECT '[]'::jsonb; -- OK jsonb ------- [] (1 row) SELECT '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'::jsonb; -- OK jsonb ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] (1 row) SELECT '[1,2]'::jsonb; -- OK jsonb -------- [1, 2] (1 row) SELECT '[1,2,]'::jsonb; -- ERROR, trailing comma ERROR: invalid input syntax for type json LINE 1: SELECT '[1,2,]'::jsonb; ^ DETAIL: Expected JSON value, but found "]". CONTEXT: JSON data, line 1: [1,2,] SELECT '[1,2'::jsonb; -- ERROR, no closing bracket ERROR: invalid input syntax for type json LINE 1: SELECT '[1,2'::jsonb; ^ DETAIL: The input string ended unexpectedly. CONTEXT: JSON data, line 1: [1,2 SELECT '[1,[2]'::jsonb; -- ERROR, no closing bracket ERROR: invalid input syntax for type json LINE 1: SELECT '[1,[2]'::jsonb; ^ DETAIL: The input string ended unexpectedly. CONTEXT: JSON data, line 1: [1,[2] -- Objects. SELECT '{}'::jsonb; -- OK jsonb ------- {} (1 row) SELECT '{"abc"}'::jsonb; -- ERROR, no value ERROR: invalid input syntax for type json LINE 1: SELECT '{"abc"}'::jsonb; ^ DETAIL: Expected ":", but found "}". CONTEXT: JSON data, line 1: {"abc"} SELECT '{"abc":1}'::jsonb; -- OK jsonb ------------ {"abc": 1} (1 row) SELECT '{1:"abc"}'::jsonb; -- ERROR, keys must be strings ERROR: invalid input syntax for type json LINE 1: SELECT '{1:"abc"}'::jsonb; ^ DETAIL: Expected string or "}", but found "1". CONTEXT: JSON data, line 1: {1... SELECT '{"abc",1}'::jsonb; -- ERROR, wrong separator ERROR: invalid input syntax for type json LINE 1: SELECT '{"abc",1}'::jsonb; ^ DETAIL: Expected ":", but found ",". CONTEXT: JSON data, line 1: {"abc",... SELECT '{"abc"=1}'::jsonb; -- ERROR, totally wrong separator ERROR: invalid input syntax for type json LINE 1: SELECT '{"abc"=1}'::jsonb; ^ DETAIL: Token "=" is invalid. CONTEXT: JSON data, line 1: {"abc"=... SELECT '{"abc"::1}'::jsonb; -- ERROR, another wrong separator ERROR: invalid input syntax for type json LINE 1: SELECT '{"abc"::1}'::jsonb; ^ DETAIL: Expected JSON value, but found ":". CONTEXT: JSON data, line 1: {"abc"::... SELECT '{"abc":1,"def":2,"ghi":[3,4],"hij":{"klm":5,"nop":[6]}}'::jsonb; -- OK jsonb -------------------------------------------------------------------- {"abc": 1, "def": 2, "ghi": [3, 4], "hij": {"klm": 5, "nop": [6]}} (1 row) SELECT '{"abc":1:2}'::jsonb; -- ERROR, colon in wrong spot ERROR: invalid input syntax for type json LINE 1: SELECT '{"abc":1:2}'::jsonb; ^ DETAIL: Expected "," or "}", but found ":". CONTEXT: JSON data, line 1: {"abc":1:... SELECT '{"abc":1,3}'::jsonb; -- ERROR, no value ERROR: invalid input syntax for type json LINE 1: SELECT '{"abc":1,3}'::jsonb; ^ DETAIL: Expected string, but found "3". CONTEXT: JSON data, line 1: {"abc":1,3... -- Miscellaneous stuff. SELECT 'true'::jsonb; -- OK jsonb ------- true (1 row) SELECT 'false'::jsonb; -- OK jsonb ------- false (1 row) SELECT 'null'::jsonb; -- OK jsonb ------- null (1 row) SELECT ' true '::jsonb; -- OK, even with extra whitespace jsonb ------- true (1 row) SELECT 'true false'::jsonb; -- ERROR, too many values ERROR: invalid input syntax for type json LINE 1: SELECT 'true false'::jsonb; ^ DETAIL: Expected end of input, but found "false". CONTEXT: JSON data, line 1: true false SELECT 'true, false'::jsonb; -- ERROR, too many values ERROR: invalid input syntax for type json LINE 1: SELECT 'true, false'::jsonb; ^ DETAIL: Expected end of input, but found ",". CONTEXT: JSON data, line 1: true,... SELECT 'truf'::jsonb; -- ERROR, not a keyword ERROR: invalid input syntax for type json LINE 1: SELECT 'truf'::jsonb; ^ DETAIL: Token "truf" is invalid. CONTEXT: JSON data, line 1: truf SELECT 'trues'::jsonb; -- ERROR, not a keyword ERROR: invalid input syntax for type json LINE 1: SELECT 'trues'::jsonb; ^ DETAIL: Token "trues" is invalid. CONTEXT: JSON data, line 1: trues SELECT ''::jsonb; -- ERROR, no value ERROR: invalid input syntax for type json LINE 1: SELECT ''::jsonb; ^ DETAIL: The input string ended unexpectedly. CONTEXT: JSON data, line 1: SELECT ' '::jsonb; -- ERROR, no value ERROR: invalid input syntax for type json LINE 1: SELECT ' '::jsonb; ^ DETAIL: The input string ended unexpectedly. CONTEXT: JSON data, line 1: -- make sure jsonb is passed through json generators without being escaped SELECT array_to_json(ARRAY [jsonb '{"a":1}', jsonb '{"b":[2,3]}']); array_to_json -------------------------- [{"a": 1},{"b": [2, 3]}] (1 row) -- jsonb extraction functions CREATE TEMP TABLE test_jsonb ( json_type text, test_json jsonb ); INSERT INTO test_jsonb VALUES ('scalar','"a scalar"'), ('array','["zero", "one","two",null,"four","five", [1,2,3],{"f1":9}]'), ('object','{"field1":"val1","field2":"val2","field3":null, "field4": 4, "field5": [1,2,3], "field6": {"f1":9}}'); SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'scalar'; ERROR: cannot call jsonb_object_field (jsonb -> text operator) on a scalar SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'array'; ERROR: cannot call jsonb_object_field (jsonb -> text operator) on an array SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'object'; ?column? ---------- (1 row) SELECT test_json -> 'field2' FROM test_jsonb WHERE json_type = 'object'; ?column? ---------- "val2" (1 row) SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'scalar'; ERROR: cannot call jsonb_object_field_text (jsonb ->> text operator) on a scalar SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'array'; ERROR: cannot call jsonb_object_field_text (jsonb ->> text operator) on an array SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'object'; ?column? ---------- val2 (1 row) SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'scalar'; ERROR: cannot call jsonb_array_element (jsonb -> int operator) on a scalar SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'array'; ?column? ---------- "two" (1 row) SELECT test_json -> 9 FROM test_jsonb WHERE json_type = 'array'; ?column? ---------- (1 row) SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'object'; ERROR: cannot call jsonb_array_element (jsonb -> int operator) on an object SELECT test_json ->> 6 FROM test_jsonb WHERE json_type = 'array'; ?column? ----------- [1, 2, 3] (1 row) SELECT test_json ->> 7 FROM test_jsonb WHERE json_type = 'array'; ?column? ----------- {"f1": 9} (1 row) SELECT test_json ->> 'field4' FROM test_jsonb WHERE json_type = 'object'; ?column? ---------- 4 (1 row) SELECT test_json ->> 'field5' FROM test_jsonb WHERE json_type = 'object'; ?column? ----------- [1, 2, 3] (1 row) SELECT test_json ->> 'field6' FROM test_jsonb WHERE json_type = 'object'; ?column? ----------- {"f1": 9} (1 row) SELECT test_json ->> 2 FROM test_jsonb WHERE json_type = 'scalar'; ERROR: cannot call jsonb_array_element_text on a scalar SELECT test_json ->> 2 FROM test_jsonb WHERE json_type = 'array'; ?column? ---------- two (1 row) SELECT test_json ->> 2 FROM test_jsonb WHERE json_type = 'object'; ERROR: cannot call jsonb_array_element_text on an object SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'scalar'; ERROR: cannot call jsonb_object_keys on a scalar SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'array'; ERROR: cannot call jsonb_object_keys on an array SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'object'; jsonb_object_keys ------------------- field1 field2 field3 field4 field5 field6 (6 rows) -- nulls SELECT (test_json->'field3') IS NULL AS expect_false FROM test_jsonb WHERE json_type = 'object'; expect_false -------------- f (1 row) SELECT (test_json->>'field3') IS NULL AS expect_true FROM test_jsonb WHERE json_type = 'object'; expect_true ------------- t (1 row) SELECT (test_json->3) IS NULL AS expect_false FROM test_jsonb WHERE json_type = 'array'; expect_false -------------- f (1 row) SELECT (test_json->>3) IS NULL AS expect_true FROM test_jsonb WHERE json_type = 'array'; expect_true ------------- t (1 row) -- equality and inequality SELECT '{"x":"y"}'::jsonb = '{"x":"y"}'::jsonb; ?column? ---------- t (1 row) SELECT '{"x":"y"}'::jsonb = '{"x":"z"}'::jsonb; ?column? ---------- f (1 row) SELECT '{"x":"y"}'::jsonb <> '{"x":"y"}'::jsonb; ?column? ---------- f (1 row) SELECT '{"x":"y"}'::jsonb <> '{"x":"z"}'::jsonb; ?column? ---------- t (1 row) -- containment SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b"}'); jsonb_contains ---------------- t (1 row) SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b", "c":null}'); jsonb_contains ---------------- t (1 row) SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b", "g":null}'); jsonb_contains ---------------- f (1 row) SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"g":null}'); jsonb_contains ---------------- f (1 row) SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"c"}'); jsonb_contains ---------------- f (1 row) SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b"}'); jsonb_contains ---------------- t (1 row) SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b", "c":"q"}'); jsonb_contains ---------------- f (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b"}'; ?column? ---------- t (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b", "c":null}'; ?column? ---------- t (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b", "g":null}'; ?column? ---------- f (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"g":null}'; ?column? ---------- f (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"c"}'; ?column? ---------- f (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b"}'; ?column? ---------- t (1 row) SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b", "c":"q"}'; ?column? ---------- f (1 row) SELECT jsonb_contained('{"a":"b"}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- t (1 row) SELECT jsonb_contained('{"a":"b", "c":null}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- t (1 row) SELECT jsonb_contained('{"a":"b", "g":null}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- f (1 row) SELECT jsonb_contained('{"g":null}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- f (1 row) SELECT jsonb_contained('{"a":"c"}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- f (1 row) SELECT jsonb_contained('{"a":"b"}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- t (1 row) SELECT jsonb_contained('{"a":"b", "c":"q"}', '{"a":"b", "b":1, "c":null}'); jsonb_contained ----------------- f (1 row) SELECT '{"a":"b"}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- t (1 row) SELECT '{"a":"b", "c":null}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- t (1 row) SELECT '{"a":"b", "g":null}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- f (1 row) SELECT '{"g":null}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- f (1 row) SELECT '{"a":"c"}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- f (1 row) SELECT '{"a":"b"}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- t (1 row) SELECT '{"a":"b", "c":"q"}'::jsonb <@ '{"a":"b", "b":1, "c":null}'; ?column? ---------- f (1 row) -- Raw scalar may contain another raw scalar, array may contain a raw scalar SELECT '[5]'::jsonb @> '[5]'; ?column? ---------- t (1 row) SELECT '5'::jsonb @> '5'; ?column? ---------- t (1 row) SELECT '[5]'::jsonb @> '5'; ?column? ---------- t (1 row) -- But a raw scalar cannot contain an array SELECT '5'::jsonb @> '[5]'; ?column? ---------- f (1 row) -- In general, one thing should always contain itself. Test array containment: SELECT '["9", ["7", "3"], 1]'::jsonb @> '["9", ["7", "3"], 1]'::jsonb; ?column? ---------- t (1 row) SELECT '["9", ["7", "3"], ["1"]]'::jsonb @> '["9", ["7", "3"], ["1"]]'::jsonb; ?column? ---------- t (1 row) -- array containment string matching confusion bug SELECT '{ "name": "Bob", "tags": [ "enim", "qui"]}'::jsonb @> '{"tags":["qu"]}'; ?column? ---------- f (1 row) -- array length SELECT jsonb_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]'); jsonb_array_length -------------------- 5 (1 row) SELECT jsonb_array_length('[]'); jsonb_array_length -------------------- 0 (1 row) SELECT jsonb_array_length('{"f1":1,"f2":[5,6]}'); ERROR: cannot get array length of a non-array SELECT jsonb_array_length('4'); ERROR: cannot get array length of a scalar -- each SELECT jsonb_each('{"f1":[1,2,3],"f2":{"f3":1},"f4":null}'); jsonb_each -------------------- (f1,"[1, 2, 3]") (f2,"{""f3"": 1}") (f4,null) (3 rows) SELECT jsonb_each('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q; q ------------------------------------------------------ (1,"""first""") (a,"{""1"": ""first"", ""b"": ""c"", ""c"": ""b""}") (b,"[1, 2]") (c,"""cc""") (n,null) (5 rows) SELECT * FROM jsonb_each('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":99,"f6":"stringy"}') q; key | value -----+----------- f1 | [1, 2, 3] f2 | {"f3": 1} f4 | null f5 | 99 f6 | "stringy" (5 rows) SELECT * FROM jsonb_each('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q; key | value -----+------------------------------------ 1 | "first" a | {"1": "first", "b": "c", "c": "b"} b | [1, 2] c | "cc" n | null (5 rows) SELECT jsonb_each_text('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":"null"}'); jsonb_each_text -------------------- (f1,"[1, 2, 3]") (f2,"{""f3"": 1}") (f4,) (f5,null) (4 rows) SELECT jsonb_each_text('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q; q ------------------------------------------------------ (1,first) (a,"{""1"": ""first"", ""b"": ""c"", ""c"": ""b""}") (b,"[1, 2]") (c,cc) (n,) (5 rows) SELECT * FROM jsonb_each_text('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":99,"f6":"stringy"}') q; key | value -----+----------- f1 | [1, 2, 3] f2 | {"f3": 1} f4 | f5 | 99 f6 | stringy (5 rows) SELECT * FROM jsonb_each_text('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q; key | value -----+------------------------------------ 1 | first a | {"1": "first", "b": "c", "c": "b"} b | [1, 2] c | cc n | (5 rows) -- exists SELECT jsonb_exists('{"a":null, "b":"qq"}', 'a'); jsonb_exists -------------- t (1 row) SELECT jsonb_exists('{"a":null, "b":"qq"}', 'b'); jsonb_exists -------------- t (1 row) SELECT jsonb_exists('{"a":null, "b":"qq"}', 'c'); jsonb_exists -------------- f (1 row) SELECT jsonb_exists('{"a":"null", "b":"qq"}', 'a'); jsonb_exists -------------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ? 'a'; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ? 'b'; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ? 'c'; ?column? ---------- f (1 row) SELECT jsonb '{"a":"null", "b":"qq"}' ? 'a'; ?column? ---------- t (1 row) -- array exists - array elements should behave as keys SELECT count(*) from testjsonb WHERE j->'array' ? 'bar'; count ------- 3 (1 row) -- type sensitive array exists - should return no rows (since "exists" only -- matches strings that are either object keys or array elements) SELECT count(*) from testjsonb WHERE j->'array' ? '5'::text; count ------- 0 (1 row) -- However, a raw scalar is *contained* within the array SELECT count(*) from testjsonb WHERE j->'array' @> '5'::jsonb; count ------- 1 (1 row) SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['a','b']); jsonb_exists_any ------------------ t (1 row) SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['b','a']); jsonb_exists_any ------------------ t (1 row) SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['c','a']); jsonb_exists_any ------------------ t (1 row) SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['c','d']); jsonb_exists_any ------------------ f (1 row) SELECT jsonb_exists_any('{"a":null, "b":"qq"}', '{}'::text[]); jsonb_exists_any ------------------ f (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['a','b']; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['b','a']; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['c','a']; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['c','d']; ?column? ---------- f (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?| '{}'::text[]; ?column? ---------- f (1 row) SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['a','b']); jsonb_exists_all ------------------ t (1 row) SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['b','a']); jsonb_exists_all ------------------ t (1 row) SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['c','a']); jsonb_exists_all ------------------ f (1 row) SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['c','d']); jsonb_exists_all ------------------ f (1 row) SELECT jsonb_exists_all('{"a":null, "b":"qq"}', '{}'::text[]); jsonb_exists_all ------------------ t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['a','b']; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['b','a']; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['c','a']; ?column? ---------- f (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['c','d']; ?column? ---------- f (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['a','a', 'b', 'b', 'b']; ?column? ---------- t (1 row) SELECT jsonb '{"a":null, "b":"qq"}' ?& '{}'::text[]; ?column? ---------- t (1 row) -- typeof SELECT jsonb_typeof('{}') AS object; object -------- object (1 row) SELECT jsonb_typeof('{"c":3,"p":"o"}') AS object; object -------- object (1 row) SELECT jsonb_typeof('[]') AS array; array ------- array (1 row) SELECT jsonb_typeof('["a", 1]') AS array; array ------- array (1 row) SELECT jsonb_typeof('null') AS "null"; null ------ null (1 row) SELECT jsonb_typeof('1') AS number; number -------- number (1 row) SELECT jsonb_typeof('-1') AS number; number -------- number (1 row) SELECT jsonb_typeof('1.0') AS number; number -------- number (1 row) SELECT jsonb_typeof('1e2') AS number; number -------- number (1 row) SELECT jsonb_typeof('-1.0') AS number; number -------- number (1 row) SELECT jsonb_typeof('true') AS boolean; boolean --------- boolean (1 row) SELECT jsonb_typeof('false') AS boolean; boolean --------- boolean (1 row) SELECT jsonb_typeof('"hello"') AS string; string -------- string (1 row) SELECT jsonb_typeof('"true"') AS string; string -------- string (1 row) SELECT jsonb_typeof('"1.0"') AS string; string -------- string (1 row) -- extract_path, extract_path_as_text SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f4','f6'); jsonb_extract_path -------------------- "stringy" (1 row) SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f2'); jsonb_extract_path -------------------- {"f3": 1} (1 row) SELECT jsonb_extract_path('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',0::text); jsonb_extract_path -------------------- "f3" (1 row) SELECT jsonb_extract_path('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',1::text); jsonb_extract_path -------------------- 1 (1 row) SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f4','f6'); jsonb_extract_path_text ------------------------- stringy (1 row) SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f2'); jsonb_extract_path_text ------------------------- {"f3": 1} (1 row) SELECT jsonb_extract_path_text('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',0::text); jsonb_extract_path_text ------------------------- f3 (1 row) SELECT jsonb_extract_path_text('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',1::text); jsonb_extract_path_text ------------------------- 1 (1 row) -- extract_path nulls SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":null,"f6":"stringy"}}','f4','f5') IS NULL AS expect_false; expect_false -------------- f (1 row) SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":null,"f6":"stringy"}}','f4','f5') IS NULL AS expect_true; expect_true ------------- t (1 row) SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":[0,1,2,null]}','f4','3') IS NULL AS expect_false; expect_false -------------- f (1 row) SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":[0,1,2,null]}','f4','3') IS NULL AS expect_true; expect_true ------------- t (1 row) -- extract_path operators SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f4','f6']; ?column? ----------- "stringy" (1 row) SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f2']; ?column? ----------- {"f3": 1} (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f2','0']; ?column? ---------- "f3" (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f2','1']; ?column? ---------- 1 (1 row) SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f4','f6']; ?column? ---------- stringy (1 row) SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f2']; ?column? ----------- {"f3": 1} (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f2','0']; ?column? ---------- f3 (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f2','1']; ?column? ---------- 1 (1 row) -- same using array literals SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>'{f4,f6}'; ?column? ----------- "stringy" (1 row) SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>'{f2}'; ?column? ----------- {"f3": 1} (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>'{f2,0}'; ?column? ---------- "f3" (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>'{f2,1}'; ?column? ---------- 1 (1 row) SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>'{f4,f6}'; ?column? ---------- stringy (1 row) SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>'{f2}'; ?column? ----------- {"f3": 1} (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>'{f2,0}'; ?column? ---------- f3 (1 row) SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>'{f2,1}'; ?column? ---------- 1 (1 row) -- same on jsonb scalars (expecting errors) SELECT '42'::jsonb#>array['f2']; ERROR: cannot call extract path from a scalar SELECT '42'::jsonb#>array['0']; ERROR: cannot call extract path from a scalar SELECT '42'::jsonb#>>array['f2']; ERROR: cannot call extract path from a scalar SELECT '42'::jsonb#>>array['0']; ERROR: cannot call extract path from a scalar -- array_elements SELECT jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false]'); jsonb_array_elements ---------------------------- 1 true [1, [2, 3]] null {"f1": 1, "f2": [7, 8, 9]} false (6 rows) SELECT * FROM jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false]') q; value ---------------------------- 1 true [1, [2, 3]] null {"f1": 1, "f2": [7, 8, 9]} false (6 rows) SELECT jsonb_array_elements_text('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false,"stringy"]'); jsonb_array_elements_text ---------------------------- 1 true [1, [2, 3]] {"f1": 1, "f2": [7, 8, 9]} false stringy (7 rows) SELECT * FROM jsonb_array_elements_text('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false,"stringy"]') q; value ---------------------------- 1 true [1, [2, 3]] {"f1": 1, "f2": [7, 8, 9]} false stringy (7 rows) -- populate_record CREATE TYPE jbpop AS (a text, b int, c timestamp); SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":"blurfl","x":43.2}') q; a | b | c --------+---+--- blurfl | | (1 row) SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":"blurfl","x":43.2}') q; a | b | c --------+---+-------------------------- blurfl | 3 | Mon Dec 31 15:30:56 2012 (1 row) SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":"blurfl","x":43.2}', true) q; a | b | c --------+---+--- blurfl | | (1 row) SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":"blurfl","x":43.2}', true) q; a | b | c --------+---+-------------------------- blurfl | 3 | Mon Dec 31 15:30:56 2012 (1 row) SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":[100,200,false],"x":43.2}', true) q; a | b | c -------------------+---+--- [100, 200, false] | | (1 row) SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":[100,200,false],"x":43.2}', true) q; a | b | c -------------------+---+-------------------------- [100, 200, false] | 3 | Mon Dec 31 15:30:56 2012 (1 row) SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"c":[100,200,false],"x":43.2}', true) q; ERROR: invalid input syntax for type timestamp: "[100, 200, false]" -- populate_recordset SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]',false) q; a | b | c --------+---+-------------------------- blurfl | | | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]',false) q; a | b | c --------+----+-------------------------- blurfl | 99 | def | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]',true) q; a | b | c --------+---+-------------------------- blurfl | | | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]',true) q; a | b | c --------+----+-------------------------- blurfl | 99 | def | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]',true) q; a | b | c -----------------+----+-------------------------- [100, 200, 300] | 99 | {"z": true} | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]',true) q; ERROR: invalid input syntax for type timestamp: "[100, 200, 300]" -- using the default use_json_as_text argument SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q; a | b | c --------+---+-------------------------- blurfl | | | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q; a | b | c --------+----+-------------------------- blurfl | 99 | def | 3 | Fri Jan 20 10:42:53 2012 (2 rows) SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q; ERROR: cannot populate with a nested object unless use_json_as_text is true SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q; ERROR: cannot populate with a nested object unless use_json_as_text is true -- handling of unicode surrogate pairs SELECT octet_length((jsonb '{ "a": "\ud83d\ude04\ud83d\udc36" }' -> 'a')::text) AS correct_in_utf8; correct_in_utf8 ----------------- 10 (1 row) SELECT jsonb '{ "a": "\ud83d\ud83d" }' -> 'a'; -- 2 high surrogates in a row ERROR: invalid input syntax for type json LINE 1: SELECT jsonb '{ "a": "\ud83d\ud83d" }' -> 'a'; ^ DETAIL: Unicode high surrogate must not follow a high surrogate. CONTEXT: JSON data, line 1: { "a":... SELECT jsonb '{ "a": "\ude04\ud83d" }' -> 'a'; -- surrogates in wrong order ERROR: invalid input syntax for type json LINE 1: SELECT jsonb '{ "a": "\ude04\ud83d" }' -> 'a'; ^ DETAIL: Unicode low surrogate must follow a high surrogate. CONTEXT: JSON data, line 1: { "a":... SELECT jsonb '{ "a": "\ud83dX" }' -> 'a'; -- orphan high surrogate ERROR: invalid input syntax for type json LINE 1: SELECT jsonb '{ "a": "\ud83dX" }' -> 'a'; ^ DETAIL: Unicode low surrogate must follow a high surrogate. CONTEXT: JSON data, line 1: { "a":... SELECT jsonb '{ "a": "\ude04X" }' -> 'a'; -- orphan low surrogate ERROR: invalid input syntax for type json LINE 1: SELECT jsonb '{ "a": "\ude04X" }' -> 'a'; ^ DETAIL: Unicode low surrogate must follow a high surrogate. CONTEXT: JSON data, line 1: { "a":... -- handling of simple unicode escapes SELECT jsonb '{ "a": "the Copyright \u00a9 sign" }' ->> 'a' AS correct_in_utf8; correct_in_utf8 ---------------------- the Copyright © sign (1 row) SELECT jsonb '{ "a": "dollar \u0024 character" }' ->> 'a' AS correct_everyWHERE; correct_everywhere -------------------- dollar $ character (1 row) SELECT jsonb '{ "a": "null \u0000 escape" }' ->> 'a' AS not_unescaped; not_unescaped -------------------- null \u0000 escape (1 row) -- indexing SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}'; count ------- 1 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}'; count ------- 15 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j ? 'public'; count ------- 194 (1 row) SELECT count(*) FROM testjsonb WHERE j ?| ARRAY['public','disabled']; count ------- 337 (1 row) SELECT count(*) FROM testjsonb WHERE j ?& ARRAY['public','disabled']; count ------- 42 (1 row) CREATE INDEX jidx ON testjsonb USING gin (j); SET enable_seqscan = off; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}'; count ------- 1 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}'; count ------- 15 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"array":["foo"]}'; count ------- 3 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"array":["bar"]}'; count ------- 3 (1 row) -- excercise GIN_SEARCH_MODE_ALL SELECT count(*) FROM testjsonb WHERE j @> '{}'; count ------- 1009 (1 row) SELECT count(*) FROM testjsonb WHERE j ? 'public'; count ------- 194 (1 row) SELECT count(*) FROM testjsonb WHERE j ?| ARRAY['public','disabled']; count ------- 337 (1 row) SELECT count(*) FROM testjsonb WHERE j ?& ARRAY['public','disabled']; count ------- 42 (1 row) -- array exists - array elements should behave as keys (for GIN index scans too) CREATE INDEX jidx_array ON testjsonb USING gin((j->'array')); SELECT count(*) from testjsonb WHERE j->'array' ? 'bar'; count ------- 3 (1 row) -- type sensitive array exists - should return no rows (since "exists" only -- matches strings that are either object keys or array elements) SELECT count(*) from testjsonb WHERE j->'array' ? '5'::text; count ------- 0 (1 row) -- However, a raw scalar is *contained* within the array SELECT count(*) from testjsonb WHERE j->'array' @> '5'::jsonb; count ------- 1 (1 row) RESET enable_seqscan; SELECT count(*) FROM (SELECT (jsonb_each(j)).key FROM testjsonb) AS wow; count ------- 4788 (1 row) SELECT key, count(*) FROM (SELECT (jsonb_each(j)).key FROM testjsonb) AS wow GROUP BY key ORDER BY count DESC, key; key | count -----------+------- line | 884 query | 207 pos | 203 node | 202 space | 197 status | 195 public | 194 title | 190 wait | 190 org | 189 user | 189 coauthors | 188 disabled | 185 indexed | 184 cleaned | 180 bad | 179 date | 179 world | 176 state | 172 subtitle | 169 auth | 168 abstract | 161 array | 5 age | 2 (24 rows) -- sort/hash SELECT count(distinct j) FROM testjsonb; count ------- 891 (1 row) SET enable_hashagg = off; SELECT count(*) FROM (SELECT j FROM (SELECT * FROM testjsonb UNION ALL SELECT * FROM testjsonb) js GROUP BY j) js2; count ------- 891 (1 row) SET enable_hashagg = on; SET enable_sort = off; SELECT count(*) FROM (SELECT j FROM (SELECT * FROM testjsonb UNION ALL SELECT * FROM testjsonb) js GROUP BY j) js2; count ------- 891 (1 row) SELECT distinct * FROM (values (jsonb '{}' || ''),('{}')) v(j); j ---- {} (1 row) SET enable_sort = on; RESET enable_hashagg; RESET enable_sort; DROP INDEX jidx; DROP INDEX jidx_array; -- btree CREATE INDEX jidx ON testjsonb USING btree (j); SET enable_seqscan = off; SELECT count(*) FROM testjsonb WHERE j > '{"p":1}'; count ------- 884 (1 row) SELECT count(*) FROM testjsonb WHERE j = '{"pos":98, "line":371, "node":"CBA", "indexed":true}'; count ------- 1 (1 row) --gin hash DROP INDEX jidx; CREATE INDEX jidx ON testjsonb USING gin (j jsonb_hash_ops); SET enable_seqscan = off; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}'; count ------- 1 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}'; count ------- 15 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}'; count ------- 2 (1 row) SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}'; count ------- 2 (1 row) -- excercise GIN_SEARCH_MODE_ALL SELECT count(*) FROM testjsonb WHERE j @> '{}'; count ------- 1009 (1 row) RESET enable_seqscan; DROP INDEX jidx; -- nested tests SELECT '{"ff":{"a":12,"b":16}}'::jsonb; jsonb ---------------------------- {"ff": {"a": 12, "b": 16}} (1 row) SELECT '{"ff":{"a":12,"b":16},"qq":123}'::jsonb; jsonb --------------------------------------- {"ff": {"a": 12, "b": 16}, "qq": 123} (1 row) SELECT '{"aa":["a","aaa"],"qq":{"a":12,"b":16,"c":["c1","c2"],"d":{"d1":"d1","d2":"d2","d1":"d3"}}}'::jsonb; jsonb -------------------------------------------------------------------------------------------------- {"aa": ["a", "aaa"], "qq": {"a": 12, "b": 16, "c": ["c1", "c2"], "d": {"d1": "d3", "d2": "d2"}}} (1 row) SELECT '{"aa":["a","aaa"],"qq":{"a":"12","b":"16","c":["c1","c2"],"d":{"d1":"d1","d2":"d2"}}}'::jsonb; jsonb ------------------------------------------------------------------------------------------------------ {"aa": ["a", "aaa"], "qq": {"a": "12", "b": "16", "c": ["c1", "c2"], "d": {"d1": "d1", "d2": "d2"}}} (1 row) SELECT '{"aa":["a","aaa"],"qq":{"a":"12","b":"16","c":["c1","c2",["c3"],{"c4":4}],"d":{"d1":"d1","d2":"d2"}}}'::jsonb; jsonb ------------------------------------------------------------------------------------------------------------------------- {"aa": ["a", "aaa"], "qq": {"a": "12", "b": "16", "c": ["c1", "c2", ["c3"], {"c4": 4}], "d": {"d1": "d1", "d2": "d2"}}} (1 row) SELECT '{"ff":["a","aaa"]}'::jsonb; jsonb ---------------------- {"ff": ["a", "aaa"]} (1 row) SELECT '{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'ff', '{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'qq', ('{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'Y') IS NULL AS f, ('{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb ->> 'Y') IS NULL AS t, '{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'x'; ?column? | ?column? | f | t | ?column? --------------------+----------+---+---+---------- {"a": 12, "b": 16} | 123 | f | t | [1, 2] (1 row) -- nested containment SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[1,2]}'; ?column? ---------- t (1 row) SELECT '{"a":[2,1],"c":"b"}'::jsonb @> '{"a":[1,2]}'; ?column? ---------- t (1 row) SELECT '{"a":{"1":2},"c":"b"}'::jsonb @> '{"a":[1,2]}'; ?column? ---------- f (1 row) SELECT '{"a":{"2":1},"c":"b"}'::jsonb @> '{"a":[1,2]}'; ?column? ---------- f (1 row) SELECT '{"a":{"1":2},"c":"b"}'::jsonb @> '{"a":{"1":2}}'; ?column? ---------- t (1 row) SELECT '{"a":{"2":1},"c":"b"}'::jsonb @> '{"a":{"1":2}}'; ?column? ---------- f (1 row) SELECT '["a","b"]'::jsonb @> '["a","b","c","b"]'; ?column? ---------- f (1 row) SELECT '["a","b","c","b"]'::jsonb @> '["a","b"]'; ?column? ---------- t (1 row) SELECT '["a","b","c",[1,2]]'::jsonb @> '["a",[1,2]]'; ?column? ---------- t (1 row) SELECT '["a","b","c",[1,2]]'::jsonb @> '["b",[1,2]]'; ?column? ---------- t (1 row) SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[1]}'; ?column? ---------- t (1 row) SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[2]}'; ?column? ---------- t (1 row) SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[3]}'; ?column? ---------- f (1 row) SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"c":3}]}'; ?column? ---------- t (1 row) SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4}]}'; ?column? ---------- t (1 row) SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4},3]}'; ?column? ---------- f (1 row) SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4},1]}'; ?column? ---------- t (1 row) -- nested object field / array index lookup SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'n'; ?column? ---------- null (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'a'; ?column? ---------- 1 (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'b'; ?column? ---------- [1, 2] (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'c'; ?column? ---------- {"1": 2} (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'd'; ?column? --------------- {"1": [2, 3]} (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'd' -> '1'; ?column? ---------- [2, 3] (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'e'; ?column? ---------- (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 0; --expecting error ERROR: cannot call jsonb_array_element (jsonb -> int operator) on an object SELECT '["a","b","c",[1,2],null]'::jsonb -> 0; ?column? ---------- "a" (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> 1; ?column? ---------- "b" (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> 2; ?column? ---------- "c" (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> 3; ?column? ---------- [1, 2] (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> 3 -> 1; ?column? ---------- 2 (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> 4; ?column? ---------- null (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> 5; ?column? ---------- (1 row) SELECT '["a","b","c",[1,2],null]'::jsonb -> -1; ?column? ---------- (1 row) --nested path extraction SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{0}'; ?column? ---------- (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{a}'; ?column? ---------- "b" (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c}'; ?column? ----------- [1, 2, 3] (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,0}'; ?column? ---------- 1 (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,1}'; ?column? ---------- 2 (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,2}'; ?column? ---------- 3 (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,3}'; ?column? ---------- (1 row) SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,-1}'; ?column? ---------- (1 row) SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{0}'; ?column? ---------- 0 (1 row) SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{3}'; ?column? ---------- [3, 4] (1 row) SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{4}'; ?column? --------------- {"5": "five"} (1 row) SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{4,5}'; ?column? ---------- "five" (1 row) --nested exists SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'n'; ?column? ---------- t (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'a'; ?column? ---------- t (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'b'; ?column? ---------- t (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'c'; ?column? ---------- t (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'd'; ?column? ---------- t (1 row) SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'e'; ?column? ---------- f (1 row)