9.16. Funções e operadores de JSON #

9.16.1. Processamento e criação de dados JSON
9.16.2. A linguagem de caminho SQL/JSON
9.16.3. Funções de consulta de SQL/JSON
9.16.4. JSON_TABLE

Esta seção descreve:

Para fornecer suporte nativo a tipos de dados JSON no ambiente SQL, PostgreSQL implementa o modelo de dados SQL/JSON. Este modelo compreende sequências de itens. Cada item pode conter valores escalares SQL, com um valor nulo SQL/JSON adicional, e estruturas de dados compostas que utilizam matrizes e objetos JSON. O modelo é uma formalização do modelo de dados implícito na especificação JSON RFC 7159.

O SQL/JSON permite tratar dados JSON juntamente com dados SQL regulares, com suporte a transações, incluindo:

Para aprender mais sobre o padrão SQL/JSON, veja [sqltr-19075-6] (ISO/IEC 19075-6:2021). Para obter detalhes sobre os tipos de dados JSON com suporte pelo PostgreSQL, veja a Seção 8.14.

9.16.1. Processamento e criação de dados JSON #

A Tabela 9.47 descreve os operadores disponíveis para uso com tipos de dados JSON (veja a Seção 8.14). Além disso, os operadores de comparação usuais descritos na Tabela 9.1 estão disponíveis para o tipo de dados jsonb, embora não para o tipo de dados json. Os operadores de comparação seguem as regras de ordenação para operações de árvore-B descritas na Seção 8.14.4. Veja também na Seção 9.21 a função de agregação json_agg, que agrega valores de registro como JSON, a função de agregação json_object_agg, que agrega pares de valores em um objeto JSON, e suas equivalentes para o tipo de dados jsonb jsonb_agg e jsonb_object_agg.

Tabela 9.47. Operadores dos tipos de dados json e jsonb

Operador

Descrição

Exemplo(s)

json -> integerjson

jsonb -> integerjsonb

Extrai o n-ésimo elemento da matriz JSON (os elementos da matriz são indexados a partir de zero, mas os números inteiros negativos contam a partir do final).

'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> 2{"c":"baz"}

'[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json -> -3{"a":"foo"}

json -> textjson

jsonb -> textjsonb

Extrai o campo do objeto JSON com a chave fornecida.

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

json ->> integertext

jsonb ->> integertext

Extrai o n-ésimo elemento da matriz JSON, como o tipo de dados text.

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

json ->> texttext

jsonb ->> texttext

Extrai o campo do objeto JSON com a chave fornecida, como o tipo de dados text.

'{"a":1,"b":2}'::json ->> 'b'2

json #> text[]json

jsonb #> text[]jsonb

Extrai o subobjeto JSON no caminho especificado, onde os elementos do caminho podem ser chaves de campo ou índices de matriz.

'{"a": {"b": ["foo","bar"]}}'::json #> '{a,b,1}'"bar"

json #>> text[]text

jsonb #>> text[]text

Extrai o subobjeto JSON no caminho especificado, como o tipo de dados text.

'{"a": {"b": ["foo","bar"]}}'::json #>> '{a,b,1}'bar


Nota

Os operadores de extração de campo/elemento/caminho retornam NULL, em vez de erro, se a entrada JSON não tiver a estrutura correta para corresponder à solicitação; por exemplo, se não existir tal chave ou elemento de matriz.

Alguns outros operadores existem apenas para o tipo de dados jsonb, conforme descrito na Tabela 9.48. A Seção 8.14.4 descreve como estes operadores podem ser usados para procurar dados do tipo de dados jsonb indexados.

Tabela 9.48. Operadores adicionais para o tipo de dados jsonb

Operador

Descrição

Exemplo(s)

jsonb @> jsonbboolean

O primeiro valor JSON contém o segundo? (Veja a Seção 8.14.3 para obter detalhes sobre contém/está contido.)

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

jsonb <@ jsonbboolean

O primeiro valor JSON está contido no segundo?

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

jsonb ? textboolean

A cadeia de caracteres de texto existe como uma chave de nível superior, ou elemento de matriz, no valor JSON?

'{"a":1, "b":2}'::jsonb ? 'b't

'["a", "b", "c"]'::jsonb ? 'b't

jsonb ?| text[]boolean

Alguma das cadeias de caracteres da matriz de texto existe como chave de nível superior ou como elemento da matriz?

'{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'd']t

jsonb ?& text[]boolean

Todas as cadeias de caracteres da matriz de texto existem como chaves de nível superior ou como elementos da matriz?

'["a", "b", "c"]'::jsonb ?& array['a', 'b']t

jsonb || jsonbjsonb

Concatena dois valores do tipo de dados jsonb. A concatenação de duas matrizes gera uma matriz contendo todos os elementos de cada entrada. A concatenação de dois objetos gera um objeto contendo a união de suas chaves, tomando o valor do segundo objeto quando houver chaves duplicadas. Todos os outros casos são tratados convertendo uma entrada não matriz em uma matriz de elemento único e, em seguida, procedendo como para duas matrizes. Não opera recursivamente: apenas a matriz de nível superior ou a estrutura do objeto é mesclada.

'["a", "b"]'::jsonb || '["a", "d"]'::jsonb["a", "b", "a", "d"]

'{"a": "b"}'::jsonb || '{"c": "d"}'::jsonb{"a": "b", "c": "d"}

'[1, 2]'::jsonb || '3'::jsonb[1, 2, 3]

'{"a": "b"}'::jsonb || '42'::jsonb[{"a": "b"}, 42]

Para anexar uma matriz a outra matriz como uma única entrada, envolva-a em uma camada adicional de matriz, por exemplo:

'[1, 2]'::jsonb || jsonb_build_array('[3, 4]'::jsonb)[1, 2, [3, 4]]

jsonb - textjsonb

Exclui uma chave (e seu valor) de um objeto JSON, ou valores cadeia de caracteres que correspondem de uma matriz JSON.

'{"a": "b", "c": "d"}'::jsonb - 'a'{"c": "d"}

'["a", "b", "c", "b"]'::jsonb - 'b'["a", "c"]

jsonb - text[]jsonb

Exclui do operando esquerdo todas as chaves ou elementos de matriz que correspondem.

'{"a": "b", "c": "d"}'::jsonb - '{a,c}'::text[]{}

jsonb - integerjsonb

Exclui o elemento da matriz com o índice especificado (inteiros negativos contam a partir do final). Gera um erro se o valor JSON não for uma matriz.

'["a", "b"]'::jsonb - 1 ["a"]

jsonb #- text[]jsonb

Exclui o campo, ou elemento de matriz, no caminho especificado, onde os elementos de caminho podem ser chaves de campo ou índices de matriz.

'["a", {"b":1}]'::jsonb #- '{1,b}'["a", {}]

jsonb @? jsonpathboolean

O caminho JSON retorna algum item para o valor JSON especificado? (É útil apenas com expressões de caminho JSON padrão SQL, mas não para expressões de verificação de predicado, já que estas sempre retornam um valor.)

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

jsonb @@ jsonpathboolean

Retorna o resultado de uma verificação de predicado de caminho JSON para o valor JSON especificado. (É útil apenas para expressões de verificação de predicado, mas não para expressões de caminho JSON padrão SQL, porque retornará NULL se o resultado do caminho não for um único valor booleano.)

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


Nota

Os operadores jsonpath @? e @@ suprimem os seguintes erros: campo de objeto ou elemento de matriz ausente, tipo de item JSON inesperado, erros de data e hora e erros numéricos. As funções relacionadas a jsonpath descritas abaixo também podem ser configuradas para suprimir estes tipos de erros. Este comportamento pode ser útil ao pesquisar coleções de documentos JSON com estruturas variadas.

A Tabela 9.49 descreve as funções disponíveis para construção de valores dos tipos de dados json e jsonb. Algumas funções nesta tabela possuem a cláusula RETURNING, que especifica o tipo de dados a ser retornado. Deve ser escolhido um entre json, jsonb, bytea, uma cadeia de caracteres do tipo de dados (text, char ou varchar), ou um tipo de dados que pode ser convertido para json. Por padrão, o tipo de dados retornado é json.

Tabela 9.49. Funções de criação de tipos de dados JSON

Função

Descrição

Exemplo(s)

to_json ( anyelement ) → json

to_jsonb ( anyelement ) → jsonb

Converte qualquer valor SQL para os tipos de dados json ou jsonb. As matrizes e valores compostos são convertidos recursivamente em matrizes e objetos (matrizes multidimensionais se tornam matrizes de matrizes em JSON). Senão, se houver uma conversão do tipo de dados SQL para o tipo de dados json, a função de conversão será usada para realizar a conversão [a]; caso contrário, será produzido um valor JSON escalar. Para qualquer escalar que não seja um número, um valor booleano ou nulo, a representação de texto será usada, com escape conforme necessário para torná-lo um valor cadeia de caracteres JSON válido.

to_json('Fred said "Hi."'::text)"Fred said \"Hi.\""

to_jsonb(row(42, 'Fred said "Hi."'::text)){"f1": 42, "f2": "Fred said \"Hi.\""}

array_to_json ( anyarray [, boolean ] ) → json

Converte uma matriz SQL em uma matriz JSON. O comportamento é o mesmo da função to_json, exceto por serem adicionadas alimentações de linha (LF) entre os elementos da matriz de nível superior, se o parâmetro booleano opcional for verdade (true).

array_to_json('{{1,5},{99,100}}'::int[])[[1,5],[99,100]]

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

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

Constrói uma matriz JSON a partir de uma série de parâmetros value_expression ou a partir dos resultados de query_expression, que deve ser uma consulta SELECT retornando uma única coluna. Se for especificado ABSENT ON NULL, os valores NULL serão ignorados. Isto sempre ocorre quando é usada uma query_expression.

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

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

row_to_json ( record [, boolean ] ) → json

Converte um valor composto SQL em um objeto JSON. O comportamento é o mesmo da função to_json, exceto por serem adicionadas alimentações de linha (LF) entre os elementos de nível superior, se o parâmetro booleano opcional for verdade (true).

row_to_json(row(1,'foo')){"f1":1,"f2":"foo"}

json_build_array ( VARIADIC "any" ) → json

jsonb_build_array ( VARIADIC "any" ) → jsonb

Cria uma matriz JSON, com tipos de dados potencialmente heterogêneos, a partir de uma lista de argumentos de comprimento variável. Cada argumento é convertido segundo to_json ou to_jsonb. Cada argumento é convertido pela função to_json ou to_jsonb.

json_build_array(1, 2, 'foo', 4, 5)[1, 2, "foo", 4, 5]

json_build_object ( VARIADIC "any" ) → json

jsonb_build_object ( VARIADIC "any" ) → jsonb

Cria um objeto JSON a partir de uma lista de argumentos de comprimento variável. Por convenção, a lista de argumentos consiste em chaves e valores alternados. Os argumentos chave são convertidos em texto; os argumentos valor são convertidos pelas funções to_json ou to_jsonb.

json_build_object('foo', 1, 2, row(3,'bar')){"foo" : 1, "2" : {"f1":3,"f2":"bar"}}

json_object ( [ { key_expression { VALUE | ':' } value_expression [ FORMAT JSON [ ENCODING UTF8 ] ] }[, ...] ] [ { NULL | ABSENT } ON NULL ] [ { WITH | WITHOUT } UNIQUE [ KEYS ] ] [ RETURNING data_type [ FORMAT JSON [ ENCODING UTF8 ] ] ])

Constrói um objeto JSON com todos os pares chave/valor fornecidos, ou um objeto vazio caso não seja fornecido nenhum par. key_expression é uma expressão escalar que define a chave JSON, que é convertida para o tipo de dados text. Não pode ser NULL nem pode pertencer a um tipo de dados que tenha conversão para o tipo de dados json. Se for especificado WITH UNIQUE KEYS, não poderá haver nenhuma chave key_expression duplicada. Qualquer par para o qual value_expression seja avaliado como NULL será omitido da saída se for especificado ABSENT ON NULL; se for especificado NULL ON NULL ou a cláusula for omitida, a chave será incluída com o valor NULL.

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

json_object ( text[] ) → json

jsonb_object ( text[] ) → jsonb

Cria um objeto JSON a partir de uma matriz de texto. A matriz deve ter exatamente uma dimensão com um número par de elementos, que neste caso são considerados como pares de chave e valor alternados, ou deve ter duas dimensões, de modo que cada matriz interna tenha exatamente dois elementos, considerados como um par chave e valor. Todos os valores são convertidos em cadeias de caracteres JSON.

json_object('{a, 1, b, "def", c, 3.5}'){"a" : "1", "b" : "def", "c" : "3.5"}

json_object('{{a, 1}, {b, "def"}, {c, 3.5}}'){"a" : "1", "b" : "def", "c" : "3.5"}

json_object ( keys text[], values text[] ) → json

jsonb_object ( keys text[], values text[] ) → jsonb

Esta forma da função json_object recebe chaves e valores em pares de matrizes de texto separadas. Fora isto, é idêntica à forma de um argumento.

json_object('{a,b}', '{1,2}'){"a": "1", "b": "2"}

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

Converte a expressão fornecida, especificada como text ou cadeia bytea (em codificação UTF-8), em um valor JSON. Se expression for NULL, será retornado um valor SQL nulo. Se for especificado WITH UNIQUE, a expression não deverá conter chaves de objeto duplicadas.

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

json_scalar ( expression )

Converte um valor escalar SQL fornecido em um valor escalar JSON. Se a entrada for NULL, será retornado um valor SQL nulo. Se a entrada for um número ou um valor booleano, será retornado um número ou valor booleano correspondente no formato JSON. Para qualquer outro valor, será retornada uma cadeia de caracteres JSON.

json_scalar(123.45)123.45

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

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

Converte uma expressão SQL/JSON em uma cadeia de caracteres ou binária. A expression pode ser de qualquer tipo de dados JSON, ou de qualquer tipo de dados de cadeia de caracteres, ou do tipo de dados bytea na codificação UTF8. O tipo de dados retornado usado em RETURNING pode ser qualquer tipo de dados de cadeia de caracteres ou tipo de dados bytea. O padrão é o tipo de dados text.

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

[a] Por exemplo, a extensão hstore contém uma conversão do tipo de dados hstore para o tipo de dados json, para que os valores do tipo de dados hstore convertidos por meio das funções de criação JSON sejam representados como objetos JSON, e não como valores cadeia de caracteres primitivos.


A Tabela 9.50 detalha as possibilidades SQL/JSON para testar JSON.

Tabela 9.50. Funções de teste de SQL/JSON

Assinatura da função

Descrição

Exemplo(s)

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

Este predicado testa se a expressão em expression pode ser analisada como JSON, possivelmente de um tipo de dados especificado. Se for especificado SCALAR ou ARRAY ou OBJECT, o teste consistirá em verificar se JSON é ou não deste tipo de dados específico. Se for especificado WITH UNIQUE KEYS, então qualquer objeto na expressão expression também será testado para verificar se possui chaves duplicadas.

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

     js     | json? | scalar? | object? | array?
------------+-------+---------+---------+--------
 123        | t     | t       | f       | f
 "abc"      | t     | t       | f       | f
 {"a": "b"} | t     | f       | t       | f
 [1,2]      | t     | f       | f       | t
 abc        | f     | f       | f       | f
(5 linhas)

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

         js          | object? | array? | array w. UK? | array w/o UK?
---------------------+---------+--------+--------------+---------------
 [{"a":"1"},        +| f       | t      | f            | t
  {"b":"2","b":"3"}] |         |        |              |
(1 linha)


A Tabela 9.51 descreve as funções disponíveis para processar valores dos tipos de dados json e jsonb.

Tabela 9.51. Funções de processamento de tipos de dados JSON

Função

Descrição

Exemplo(s)

json_array_elements ( json ) → setof json

jsonb_array_elements ( jsonb ) → setof jsonb

Expande a matriz JSON de nível superior em um conjunto de valores JSON.

SELECT * FROM json_array_elements('[1,true, [2,false]]')

   value
-----------
 1
 true
 [2,false]

json_array_elements_text ( json ) → setof text

jsonb_array_elements_text ( jsonb ) → setof text

Expande a matriz JSON de nível superior em um conjunto de valores do tipo de dados text.

SELECT * FROM json_array_elements_text('["foo", "bar"]')

   value
-----------
 foo
 bar

json_array_length ( json ) → integer

jsonb_array_length ( jsonb ) → integer

Retorna o número de elementos na matriz JSON de nível superior.

json_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]')5

jsonb_array_length('[]')0

json_each ( json ) → setof record ( key text, value json )

jsonb_each ( jsonb ) → setof record ( key text, value jsonb )

Expande o objeto JSON de nível superior em um conjunto de pares de chave/valor.

SELECT * FROM json_each('{"a":"foo", "b":"bar"}')

 key | value
-----+-------
 a   | "foo"
 b   | "bar"

json_each_text ( json ) → setof record ( key text, value text )

jsonb_each_text ( jsonb ) → setof record ( key text, value text )

Expande o objeto JSON de nível superior em um conjunto de pares de chave/valor. O value retornado será do tipo de dados text.

SELECT * FROM json_each_text('{"a":"foo", "b":"bar"}')

 key | value
-----+-------
 a   | foo
 b   | bar

json_extract_path ( from_json json, VARIADIC path_elems text[] ) → json

jsonb_extract_path ( from_json jsonb, VARIADIC path_elems text[] ) → jsonb

Extrai o subobjeto JSON no caminho especificado. (É funcionalmente equivalente ao operador #>, mas escrever o caminho como uma lista de comprimento variável pode ser mais conveniente em alguns casos.)

json_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')"foo"

json_extract_path_text ( from_json json, VARIADIC path_elems text[] ) → text

jsonb_extract_path_text ( from_json jsonb, VARIADIC path_elems text[] ) → text

Extrai o subobjeto JSON no caminho especificado como o tipo de dados text. (É funcionalmente equivalente ao operador #>>.)

json_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"foo"}}', 'f4', 'f6')foo

json_object_keys ( json ) → setof text

jsonb_object_keys ( jsonb ) → setof text

Retorna o conjunto de chaves no objeto JSON de nível superior.

SELECT * FROM json_object_keys('{"f1":"abc","f2":{"f3":"a", "f4":"b"}}')

 json_object_keys
------------------
 f1
 f2

json_populate_record ( base anyelement, from_json json ) → anyelement

jsonb_populate_record ( base anyelement, from_json jsonb ) → anyelement

Expande o objeto JSON de nível superior para uma linha tendo o tipo de dados composto do argumento base. O objeto JSON é verificado em busca de campos cujos nomes correspondem aos nomes das colunas do tipo de linha de saída e seus valores são inseridos nessas colunas da saída. (Os campos que não correspondem a nenhum nome de coluna de saída são ignorados.) No uso típico, o valor para base é apenas NULL, significando que qualquer coluna de saída, que não corresponda a nenhum campo do objeto, será preenchida com nulos. No entanto, se base não for NULL, os valores que contém serão usados para as colunas sem correspondência.

Para converter um valor JSON para o tipo de dados SQL de uma coluna de saída, são aplicadas as seguintes regras em sequência:

  • Um valor JSON nulo é convertido em um SQL nulo em todos os casos.

  • Se a coluna de saída for do tipo de dados json ou jsonb, o valor JSON será reproduzido exatamente.

  • Se a coluna de saída for do tipo de dados composto (linha), e o valor JSON for um objeto JSON, os campos do objeto serão convertidos em colunas do tipo de dados da linha da saída pela aplicação recursiva dessas regras.

  • Da mesma forma, se a coluna de saída for do tipo de dados matriz, e o valor JSON for uma matriz JSON, os elementos da matriz JSON serão convertidos em elementos da matriz de saída pela aplicação recursiva dessas regras.

  • Senão, se o valor JSON for uma cadeia de caracteres, o conteúdo da cadeia de caracteres será alimentado para a função de conversão de entrada para o tipo de dados da coluna.

  • Senão, a representação de texto comum do valor JSON é alimentada para a função de conversão de entrada para o tipo de dados da coluna.

Embora o exemplo abaixo use uma constante para o valor JSON, o uso típico seria fazer uma referência lateral a uma coluna do tipo de dados json ou jsonb de outra tabela na cláusula FROM da consulta. Escrever json_populate_record na cláusula FROM é uma boa prática, porque todas as colunas extraídas ficam disponíveis para uso sem chamadas de função repetidas.

CREATE TYPE subrowtype AS (d int, e text);

CREATE TYPE myrowtype AS (a int, b text[], c subrowtype);

SELECT * FROM json_populate_record(null::myrowtype, '{"a": 1, "b": ["2", "a b"], "c": {"d": 4, "e": "a b c"}, "x": "foo"}')

 a |   b       |      c
---+-----------+-------------
 1 | {2,"a b"} | (4,"a b c")

jsonb_populate_record_valid ( base anyelement, from_json json ) → boolean

Função para testar jsonb_populate_record. Retorna true se a entrada jsonb_populate_record terminaria sem erros para o objeto JSON de entrada fornecido; ou seja, é uma entrada válida, caso contrário retorna false.

CREATE TYPE jsb_char2 AS (a char(2));

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

 jsonb_populate_record_valid
-----------------------------
 f
(1 linha)

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

ERROR:  value too long for type character(2)

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

 jsonb_populate_record_valid
-----------------------------
 t
(1 linha)

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

 a
----
 aa
(1 linha)

json_populate_recordset ( base anyelement, from_json json ) → setof anyelement

jsonb_populate_recordset ( base anyelement, from_json jsonb ) → setof anyelement

Expande a matriz de objetos JSON de nível superior para um conjunto de linhas com o tipo de dados composto do argumento base. Cada elemento da matriz JSON é processado conforme descrito acima na função json[b]_populate_record.

CREATE TYPE twoints AS (a int, b int);

SELECT * FROM json_populate_recordset(null::twoints, '[{"a":1,"b":2}, {"a":3,"b":4}]')

 a | b
---+---
 1 | 2
 3 | 4

json_to_record ( json ) → record

jsonb_to_record ( jsonb ) → record

Expande o objeto JSON de nível superior para uma linha com o tipo de dados composto definido por uma cláusula AS. (Assim como todas as funções que retornam o tipo de dados record, a consulta que chama deve definir explicitamente a estrutura do registro com uma cláusula AS.) O registro de saída é preenchido a partir de campos do objeto JSON, da mesma forma descrita acima para json[b]_populate_record. Como não há valor de registro de entrada, as colunas sem correspondência são sempre preenchidas com valores nulos.

CREATE TYPE myrowtype AS (a int, b text);

SELECT * FROM json_to_record('{"a":1,"b":[1,2,3],"c":[1,2,3],"e":"bar","r": {"a": 123, "b": "a b c"}}') as x(a int, b text, c int[], d text, r myrowtype)

 a |    b    |    c    | d |       r
---+---------+---------+---+---------------
 1 | [1,2,3] | {1,2,3} |   | (123,"a b c")

json_to_recordset ( json ) → setof record

jsonb_to_recordset ( jsonb ) → setof record

Expande a matriz de objetos JSON de nível superior para um conjunto de linhas com o tipo de dados composto definido por uma cláusula AS. (Assim como todas as funções que retornam o tipo de dados record, a consulta que chama deve definir explicitamente a estrutura do registro com uma cláusula AS.) Cada elemento da matriz JSON é processado conforme descrito acima para json[b]_populate_record.

SELECT * FROM json_to_recordset('[{"a":1,"b":"foo"}, {"a":"2","c":"bar"}]') as x(a int, b text)

 a |  b
---+-----
 1 | foo
 2 |
(2 linhas)

jsonb_set ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean ] ) → jsonb

Retorna o target (alvo) com o item designado pelo path (caminho) substituído pelo new_value (novo valor), ou com o new_value adicionado se create_if_missing (criar se estiver faltando) for verdade (true) (que é o padrão) e o item designado pelo path não existir. Todas as etapas anteriores no caminho devem existir, ou o target será retornado inalterado. Assim como os operadores orientados por caminho, os inteiros negativos que aparecem no path contam a partir do final das matrizes JSON. Se o último passo do caminho for um índice de matriz que está fora do intervalo, e create_if_missing for verdade, o novo valor ser´ adicionado no início da matriz se o índice for negativo, ou no final da matriz se for positivo.

jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', '[2,3,4]', false)[{"f1": [2, 3, 4], "f2": null}, 2, null, 3]

jsonb_set('[{"f1":1,"f2":null},2]', '{0,f3}', '[2,3,4]')[{"f1": 1, "f2": null, "f3": [2, 3, 4]}, 2]

jsonb_set_lax ( target jsonb, path text[], new_value jsonb [, create_if_missing boolean [, null_value_treatment text ]] ) → jsonb

Se new_value não for NULL, se comporta de forma idêntica a jsonb_set. Senão se comporta segundo o valor de null_value_treatment (tratamento de valor nulo), que deve ser um entre 'raise_exception', 'use_json_null', 'delete_key', ou 'return_target'. O padrão é 'use_json_null'.

jsonb_set_lax('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', null)[{"f1": null, "f2": null}, 2, null, 3]

jsonb_set_lax('[{"f1":99,"f2":null},2]', '{0,f3}', null, true, 'return_target')[{"f1": 99, "f2": null}, 2]

jsonb_insert ( target jsonb, path text[], new_value jsonb [, insert_after boolean ] ) → jsonb

Retorna target com o new_value inserido. Se o item designado pelo path for um elemento de matriz, o new_value será inserido antes desse item se insert_after (inserir após) for falso (que é o padrão), ou depois se insert_after for verdade. Se o item designado pelo path for um campo do objeto, o new_value será inserido somente se o objeto ainda não contiver esta chave. Todas as etapas anteriores no caminho devem existir, ou o target será retornado inalterado. Assim como os operadores orientados por caminho, os inteiros negativos que aparecem no path contam a partir do final das matrizes JSON. Se a última etapa do caminho for um índice de matriz fora do intervalo, o novo valor será adicionado no início da matriz se o índice for negativo ou no final da matriz se for positivo.

jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"'){"a": [0, "new_value", 1, 2]}

jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true){"a": [0, 1, "new_value", 2]}

json_strip_nulls ( target json [,strip_in_arrays boolean ] ) → json

jsonb_strip_nulls ( target jsonb [,strip_in_arrays boolean ] ) → jsonb

Remove todos os campos do objeto com valor nulo do valor JSON fornecido, recursivamente. Se strip_in_arrays for verdade (o valor padrão é falso), os elementos nulos da matriz também são removidos. Caso contrário, eles não são removidos. Valores nulos puros nunca são removidos.

json_strip_nulls('[{"f1":1, "f2":null}, 2, null, 3]')[{"f1":1},2,null,3]

jsonb_strip_nulls('[1,2,null,3,4]', true)[1,2,3,4]

jsonb_path_exists ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

Verifica se o caminho JSON retorna algum item para o valor JSON especificado. (É útil apenas com expressões de caminho JSON padrão SQL, mas não para expressões de verificação de predicado, já que estas sempre retornam um valor.) Se for especificado o argumento vars, este deverá ser um objeto JSON, e seus campos fornecerem valores com nomes a serem substituídos na expressão jsonpath . Se for especificado o argumento silent e for true, esta função irá suprimir os mesmos erros que os operadores @? e @@ suprimem.

jsonb_path_exists('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')t

jsonb_path_match ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

Retorna o resultado booleano SQL de uma verificação de predicado de caminho JSON para o valor JSON especificado. (É útil apenas para expressões de verificação de predicado, mas não para expressões de caminho JSON padrão SQL, uma vez que irá falhar ou retornar NULL se o resultado do caminho não for um único valor booleano.) Os argumentos opcionais vars e silent atuam da mesma maneira que na função jsonb_path_exists.

jsonb_path_match('{"a":[1,2,3,4,5]}', 'exists($.a[*] ? (@ >= $min && @ <= $max))', '{"min":2, "max":4}')t

jsonb_path_query ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → setof jsonb

Retorna todos os itens JSON retornados pelo caminho JSON para o valor JSON especificado. Para expressões de caminho JSON padrão SQL, retorna os valores JSON selecionados de target. Para expressões de verificação de predicado retorna o resultado da verificação do predicado: true, false ou null. Os argumentos opcionais vars e silent atuam da mesma maneira que na função jsonb_path_exists.

SELECT * FROM jsonb_path_query('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')

 jsonb_path_query
------------------
 2
 3
 4

jsonb_path_query_array ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

Retorna todos os itens JSON retornados pelo caminho JSON para o valor JSON especificado, como uma matriz JSON. Os parâmetros são os mesmos que para a função jsonb_path_query.

jsonb_path_query_array('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')[2, 3, 4]

jsonb_path_query_first ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

Retorna o primeiro item JSON retornado pelo caminho JSON para o valor JSON especificado, ou NULL se não houver resultados. Os parâmetros são os mesmos que para a função jsonb_path_query.

jsonb_path_query_first('{"a":[1,2,3,4,5]}', '$.a[*] ? (@ >= $min && @ <= $max)', '{"min":2, "max":4}')2

jsonb_path_exists_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

jsonb_path_match_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → boolean

jsonb_path_query_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → setof jsonb

jsonb_path_query_array_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

jsonb_path_query_first_tz ( target jsonb, path jsonpath [, vars jsonb [, silent boolean ]] ) → jsonb

Estas funções agem como suas contrapartes descritas acima sem o sufixo _tz, exceto por estas funções darem suporte a comparações de valores de data/hora que exigem conversões com reconhecimento de zona horária. O exemplo abaixo requer a interpretação do valor de apenas a data 2015-08-02 como um carimbo de data e hora com zona horária, portanto o resultado depende da configuração corrente de TimeZone. Devido a esta dependência, estas funções são marcadas como estáveis, significando que estas funções não podem ser usadas em índices. Suas contrapartes são imutáveis, portanto podem ser usadas em índices; mas geram erros se solicitadas a fazer tais comparações.

jsonb_path_exists_tz('["2015-08-01 12:00:00-05"]', '$[*] ? (@.datetime() < "2015-08-02".datetime())')t

jsonb_pretty ( jsonb ) → text

Converte o valor JSON fornecido em texto indentado e com impressão estruturada (pretty-printed).

jsonb_pretty('[{"f1":1,"f2":null}, 2]')

[
    {
        "f1": 1,
        "f2": null
    },
    2
]

json_typeof ( json ) → text

jsonb_typeof ( jsonb ) → text

Retorna o tipo de dados do valor JSON de nível superior como uma cadeia de caracteres de texto. Os tipos de dados possíveis são: object, array, string, number, boolean e null. (O resultado null não deve ser confundido com o NULL do SQL; veja os exemplos.)

json_typeof('-123.4')number

json_typeof('null'::json)null

json_typeof(NULL::json) IS NULLt


9.16.2. A linguagem de caminho SQL/JSON #

As expressões de caminho SQL/JSON indicam os itens a serem recuperados de um valor JSON, de forma semelhante às expressões XPath usadas para acessar conteúdo XML. No PostgreSQL, as expressões de caminho são implementadas como o tipo de dados jsonpath, podendo usar quaisquer elementos descritos na Seção 8.14.7.

As funções e operadores de consulta JSON passam a expressão de caminho fornecida para o mecanismo de caminho para avaliação. Se a expressão corresponder aos dados JSON consultados, o item JSON correspondente, ou conjunto de itens, será retornado. Se não houver correspondência, o resultado será NULL, false ou um erro, dependendo da função. As expressões de caminho são escritas na linguagem de caminho SQL/JSON, podendo incluir expressões e funções aritméticas.

Uma expressão de caminho consiste em uma sequência de elementos permitidos pelo tipo de dados jsonpath. A expressão de caminho é normalmente avaliada da esquerda para a direita, mas podem ser usados parênteses para alterar a ordem das operações. Se a avaliação for bem-sucedida, será produzida uma sequência de itens JSON e o resultado da avaliação será retornado para a função de consulta JSON que conclui a computação especificada.

Para se referir ao valor JSON que está sendo consultado (o item de contexto), deve ser usada a variável $ na expressão do caminho. O primeiro elemento de um caminho deve ser sempre o $. Este pode ser seguido por um ou mais operadores de acesso que percorrem a estrutura JSON nível por nível para recuperar subitens do item de contexto. Cada operador de acesso atua sobre o(s) resultado(s) da etapa de avaliação anterior, produzindo zero, um ou mais itens de saída a partir de cada item de entrada.

Por exemplo, suponha que temos alguns dados JSON de um rastreador GPS que gostaríamos de analisar, tal como:

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

(O exemplo acima pode ser copiado e colado no psql para configurar os exemplos a seguir. Então o psql irá expandir o :'json' em uma constante de cadeia de caracteres devidamente entre aspas contendo o valor JSON.)

Para recuperar os segmentos de trilha disponíveis, é necessário usar o operador de acesso .key para detalhar os objetos JSON ao redor:

=> SELECT jsonb_path_query(:'json', '$.track.segments');

                               jsonb_path_query
-----------------------------------------------------------------------------------
 [{"HR": 73, "location": [47.763, 13.4034], "start time": "2018-10-14 10:05:14"}, ↵
  {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}]
(1 linha)

Para recuperar o conteúdo de uma matriz, normalmente é usado o operador [*]. O exemplo a seguir retornar as coordenadas de localização para todos os segmentos de trilha disponíveis:

=> SELECT jsonb_path_query(:'json', '$.track.segments[*].location');

 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 linhas)

Aqui começamos com todo o valor de entrada JSON ($), então o acessador .track selecionou o objeto JSON associado à chave de objeto "track", então o acessador .segments selecionou a matriz JSON associada à chave "segments" dentro deste objeto, então o acessador [*] selecionou cada elemento desta matriz (produzindo uma série de itens), então o acessador .location selecionou a matriz JSON associada à chave "location" dentro de cada um destes objetos. Neste exemplo, cada um destes objetos tinha uma chave "location"; mas se algum deles não tivesse, o acessador .location simplesmente não produziria nenhuma saída para este item de entrada.

Para retornar apenas as coordenadas do primeiro segmento, pode ser especificado o índice correspondente no operador de acesso []. Lembre-se de que os índices de matrizes JSON são relativos a partir de zero:

=> SELECT jsonb_path_query(:'json', '$.track.segments[0].location');

 jsonb_path_query
-------------------
 [47.763, 13.4034]
(1 linha)

O resultado de cada etapa de avaliação de caminho pode ser processado por um ou mais dos operadores e métodos jsonpath listados na Seção 9.16.2.3. Cada nome de método deve ser precedido por um ponto. Por exemplo, pode ser obtido o tamanho de uma matriz:

=> SELECT jsonb_path_query(:'json', '$.track.segments.size()');

 jsonb_path_query
------------------
 2
(1 linha)

Mais exemplos de uso dos operadores e métodos para o tipo de dados jsonpath em expressões de caminho aparecem abaixo na Seção 9.16.2.3.

Um caminho também pode conter expressões de filtro que funcionam de forma semelhante à cláusula WHERE do SQL. Uma expressão de filtro começa com um ponto de interrogação e fornece uma condição entre parênteses:

? (condição)

As expressões de filtro devem ser escritas logo após a etapa de avaliação do caminho à qual se aplicam. O resultado desta etapa é filtrado para incluir apenas os itens que satisfazem a condição fornecida. SQL/JSON define lógica de três valores, portanto a condição pode produzir true, false, ou unknown. O valor unknown desempenha o mesmo papel que o NULL no SQL, podendo ser testado com o predicado is unknown. As etapas subsequentes de avaliação de caminho utilizam apenas os itens para os quais a expressão de filtro retornou true.

As funções e operadores que podem ser usados em expressões de filtro estão listados na Tabela 9.53. Dentro de uma expressão de filtro, a variável @ denota o valor que está sendo considerado (ou seja, um resultado da etapa de caminho anterior). Podem ser escritos operadores de acesso após o @ para recuperar os itens de componentes.

Por exemplo, suponha que se queira recuperar todos os valores de frequência cardíaca superiores a 130. Isto pode ser conseguido da seguinte maneira:

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

 jsonb_path_query
------------------
 135
(1 linha)

Para obter as horas de início dos segmentos com estes valores, é necessário filtrar os segmentos irrelevantes antes de selecionar as horas de início. Portanto, a expressão de filtro é aplicada à etapa anterior e o caminho usado na condição é diferente:

=> SELECT jsonb_path_query(:'json',
          '$.track.segments[*] ? (@.HR > 130)."start time"');

   jsonb_path_query
-----------------------
 "2018-10-14 10:39:21"
(1 linha)

Podem ser usadas várias expressões de filtro em sequência, se for necessário. O exemplo a seguir seleciona as horas de início de todos os segmentos que contêm locais com coordenadas relevantes e valores elevados de frequência cardíaca:

=> SELECT jsonb_path_query(:'json', '$.track.segments[*] ?
          (@.location[1] < 13.4) ? (@.HR > 130)."start time"');

   jsonb_path_query
-----------------------
 "2018-10-14 10:39:21"
(1 linha)

Também é permitido usar expressões de filtro em níveis diferentes de aninhamento. O exemplo a seguir primeiro filtra todos os segmentos por localização e, em seguida, retorna valores elevados de frequência cardíaca para estes segmentos, se disponíveis:

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

 jsonb_path_query
------------------
 135
(1 linha)

Também podem ser aninhadas expressões de filtro umas dentro das outras. Este exemplo retorna o tamanho da trilha se ela contiver algum segmento com valores altos de frequência cardíaca, ou uma sequência vazia caso contrário:

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

 jsonb_path_query
------------------
 2
(1 linha)

9.16.2.1. Desvios do padrão SQL #

A implementação da linguagem de caminho SQL/JSON no PostgreSQL apresenta os seguintes desvios em relação ao padrão SQL/JSON.

9.16.2.1.1. Expressões de verificação de predicados booleanos #

Como uma extensão do padrão SQL, uma expressão de caminho do PostgreSQL pode ser um predicado booleano, enquanto o padrão SQL permite predicados apenas dentro de filtros. Enquanto as expressões de caminho padrão SQL retornam o(s) elemento(s) relevante(s) do valor JSON consultado, as expressões de verificação de predicado retornam um resultado do tipo de dados jsonb com três valores possíveis para a verificação de predicado: true, false ou null. Por exemplo, poderia ser escrita esta expressão de filtro padrão SQL:

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

                                jsonb_path_query
---------------------------------------------------------------------------------
 {"HR": 135, "location": [47.706, 13.2635], "start time": "2018-10-14 10:39:21"}
(1 linha)

A expressão semelhante de verificação de predicado simplesmente retorna true indicando que existe uma correspondência:

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

 jsonb_path_query
------------------
 true
(1 linha)

Exemplo 9.3. Exemplo do tradutor

Tipo de dados retornado pela consulta acima:

SELECT pg_typeof(jsonb_path_query(:'json', '$.track.segments[*].HR > 130'));

 pg_typeof
-----------
 jsonb
(1 linha)


Nota

As expressões de verificação de predicados são requerida no operador @@ (e na função jsonb_path_match), e não devem ser usadas com o operador @? (ou com a função jsonb_path_exists).

9.16.2.1.2. Interpretação de expressões regulares #

Existem pequenas diferenças na interpretação dos padrões de expressão regular usadas ​​nos filtros like_regex. conforme descrito na Seção 9.16.2.4.

9.16.2.2. Modos Estrito e Flexível #

Ao consultar dados JSON, a expressão do caminho pode não corresponder à estrutura real dos dados JSON. Uma tentativa de acessar um membro inexistente de um objeto ou um elemento de uma matriz é definida como um erro estrutural. As expressões de caminho SQL/JSON possuem dois modos de lidar com erros estruturais:

  • lax (Flexível) (o padrão) — O mecanismo de caminho adapta implicitamente os dados consultados ao caminho especificado. Quaisquer erros estruturais que não possam ser corrigidos conforme descrito abaixo são suprimidos, não produzindo nenhuma correspondência.

  • strict (Estrito) — Se ocorrer um erro estrutural, será gerado um erro.

O modo flexível facilita a correspondência entre um documento JSON e uma expressão de caminho quando os dados JSON não estão em conformidade com o esquema esperado. Se um operando não corresponder aos requisitos de uma determinada operação, ele poderá ser automaticamente encapsulado como uma matriz SQL/JSON ou desencapsulado convertendo seus elementos em uma sequência SQL/JSON antes de executar a operação. Além disso, os operadores de comparação desempacotam automaticamente seus operandos no modo flexível, permitindo comparar matrizes SQL/JSON sem necessidade de configurações adicionais. Uma matriz de tamanho 1 é considerada igual ao seu único elemento. O desempacotamento automático não é realizado quando:

  • A expressão de caminho contém os métodos type() ou size() que retornam o tipo de dados e o número de elementos na matriz, respectivamente.

  • Os dados JSON consultados contêm matrizes aninhadas. Neste caso, apenas a matriz mais externa é desempacotada, enquanto todos as matrizes internas permanecem inalteradas. Assim, o desempacotamento implícito só pode ocorrer um nível abaixo em cada etapa de avaliação do caminho.

Por exemplo, ao consultar os dados de GPS listados acima, se pode abstrair o fato de que ele armazena uma matriz de segmentos ao usar o modo flexível:

=> SELECT jsonb_path_query(:'json', 'lax $.track.segments.location');

 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 linhas)

No modo estrito, o caminho especificado deve corresponder exatamente à estrutura do documento JSON consultado; portanto, usar esta expressão de caminho causará um erro:

=> SELECT jsonb_path_query(:'json', 'strict $.track.segments.location');
ERRO: acessador de membro jsonpath só pode ser aplicado a um objeto

Para obter o mesmo resultado que no modo flexível, é necessário desempacotar explicitamente a matriz segments:

=> SELECT jsonb_path_query(:'json', 'strict $.track.segments[*].location');

 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 linhas)

O comportamento de desempacotamento do modo flexível pode levar a resultados surpreendentes. Por exemplo, a seguinte consulta usando o acessador .** seleciona cada valor HR duas vezes:

=> SELECT jsonb_path_query(:'json', 'lax $.**.HR');

 jsonb_path_query
------------------
 73
 135
 73
 135
(4 linhas)

Isto acontece porque o acessador `.**` seleciona tanto a matriz `segments` quanto cada um de seus elementos, enquanto o acessador .HR desempacota automaticamente matrizes ao usar o modo flexível. Para evitar resultados inesperados, se recomenda usar o acessador .** somente no modo estrito. A consulta a seguir seleciona cada valor de HR apenas uma vez:

=> SELECT jsonb_path_query(:'json', 'strict $.**.HR');

 jsonb_path_query
------------------
 73
 135
(2 linhas)

O desempacotamento de matrizes também pode levar a resultados inesperados. Considere este exemplo, que seleciona todas as matrizes de location:

=> SELECT jsonb_path_query(:'json', 'lax $.track.segments[*].location');

 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 linhas)

Como esperado, retorna as matrizes completas. Mas aplicar uma expressão de filtro faz com que as matrizes sejam desempacotadas para avaliar cada item, retornando apenas os itens que correspondem à expressão:

=> SELECT jsonb_path_query(:'json', 'lax $.track.segments[*].location ?(@[*] > 15)');

 jsonb_path_query
------------------
 47.763
 47.706
(2 linhas)

Isto ocorre apesar das matrizes completas serem selecionados pela expressão do caminho. Use o modo estrito para restaurar a seleção das matrizes:

=> SELECT jsonb_path_query(:'json', 'strict $.track.segments[*].location ?(@[*] > 15)');

 jsonb_path_query
-------------------
 [47.763, 13.4034]
 [47.706, 13.2635]
(2 linhas)

9.16.2.3. Operadores e métodos de caminho SQL/JSON #

A Tabela 9.52 descreve os operadores e métodos disponíveis para o tipo de dados jsonpath. Note que, embora os operadores e métodos unários possam ser aplicados a múltiplos valores resultantes de uma etapa de caminho anterior, Os operadores binários (adição, etc.) só podem ser aplicados a valores individuais. No modo flexível, os métodos aplicados a uma matriz serão executados para cada valor na matriz. As exceções são .type() e .size(), que são aplicados à própria matriz.

Tabela 9.52. Operadores e métodos para o tipo de dados jsonpath

Operador/Método

Descrição

Exemplo(s)

number + numbernumber

Adição

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

+ numbernumber

Mais unário (sem operação); ao contrário da adição, pode iterar sobre vários valores

jsonb_path_query_array('{"x": [2,3,4]}', '+ $.x')[2, 3, 4]

number - numbernumber

Subtração

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

- numbernumber

Negação; ao contrário da subtração, pode iterar sobre vários valores

jsonb_path_query_array('{"x": [2,3,4]}', '- $.x')[-2, -3, -4]

number * numbernumber

Multiplicação

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

number / numbernumber

Divisão

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

number % numbernumber

Módulo (resto)

jsonb_path_query('[32]', '$[0] % 10')2

value . type()string

Tipo de dados do item JSON (veja a função json_typeof)

jsonb_path_query_array('[1, "2", {}]', '$[*].type()')["number", "string", "object"]

value . size()number

Tamanho do item JSON (número de elementos da matriz, ou 1 se não for uma matriz)

jsonb_path_query('{"m": [11, 15]}', '$.m.size()')2

value . boolean()boolean

Valor booleano convertido a partir de um valor booleano, número ou cadeia de caracteres em JSON.

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

value . string()string

Valor cadeia de caracteres convertido a partir de um JSON booleano, numérico, cadeia de caracteres ou data/hora.

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

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

value . double()number

Número de ponto flutuante aproximado convertido a partir de um número ou cadeia de caracteres JSON.

jsonb_path_query('{"len": "1.9"}', '$.len.double() * 2')3.8

number . ceiling()number

Número inteiro mais próximo maior ou igual ao número fornecido.

jsonb_path_query('{"h": 1.3}', '$.h.ceiling()')2

number . floor()number

Número inteiro mais próximo menor ou igual ao número fornecido.

jsonb_path_query('{"h": 1.7}', '$.h.floor()')1

number . abs()number

Valor absoluto do número fornecido

jsonb_path_query('{"z": -0.3}', '$.z.abs()')0.3

value . bigint()bigint

Valor inteiro grande convertido a partir de um número ou cadeia de caracteres JSON

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

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

Valor decimal arredondado convertido a partir de um número ou cadeia de caracteres JSON. (precision e scale devem ser valores inteiros)

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

value . integer()integer

Valor inteiro convertido a partir de um número ou cadeia de caracteres JSON

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

value . number()numeric

Valor numérico convertido a partir de um número ou cadeia de caracteres JSON

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

string . datetime()datetime_type (veja a nota)

Valor de data e hora convertido a partir de uma cadeia de caracteres

jsonb_path_query('["2015-8-1", "2015-08-12"]', '$[*] ? (@.datetime() < "2015-08-2".datetime())')"2015-8-1"

string . datetime(template)datetime_type (see note)

Valor de data e hora convertido a partir de uma cadeia de caracteres usando o modelo de to_timestamp especificado

jsonb_path_query_array('["12:30", "18:40"]', '$[*].datetime("HH24:MI")')["12:30:00", "18:40:00"]

string . date()date

Valor de data convertido a partir de uma cadeia de caracteres

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

string . time()time without time zone

Valor da hora sem zona horária convertido a partir de uma cadeia de caracteres

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

string . time(precision)time without time zone

Valor da hora sem zona horária, convertido a partir de uma cadeia de caracteres, com frações de segundo ajustadas à precisão especificada.

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

string . time_tz()time with time zone

Valor da hora com zona horária convertido a partir de uma cadeia de caracteres

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

string . time_tz(precision)time with time zone

Valor da hora com zona horária, convertido a partir de uma cadeia de caracteres, com frações de segundo ajustadas à precisão especificada.

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

string . timestamp()timestamp without time zone

Carimbo de data e hora sem valor de zona horária, convertido a partir de uma cadeia de caracteres

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

string . timestamp(precision)timestamp without time zone

Carimbo de data e hora sem valor de zona horária, convertido a partir de uma cadeia de caracteres com frações de segundo ajustadas à precisão especificada

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

string . timestamp_tz()timestamp with time zone

Carimbo de data e hora com valor de zona horária, convertido a partir de uma cadeia de caracteres

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

string . timestamp_tz(precision)timestamp with time zone

Carimbo de data e hora com valor de zona horária, convertido a partir de uma cadeia de caracteres com frações de segundo ajustadas à precisão especificada

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

object . keyvalue()array

Os pares chave-valor do objeto, representados como uma matriz de objetos contendo três campos: "key", "value" e "id"; "id" é um identificador único do objeto ao qual o par chave-valor pertence

jsonb_path_query_array('{"x": "20", "y": 32}', '$.keyvalue()')[{"id": 0, "key": "x", "value": "20"}, {"id": 0, "key": "y", "value": 32}]


Nota

O tipo de dados do resultado dos métodos datetime() e datetime(template) podem ser date, timetz, time, timestamptz ou timestamp. Os dois métodos determinam o tipo de dados do resultado dinamicamente.

O método datetime() tenta sequencialmente encontrar uma correspondência entre sua cadeia de caracteres de entrada e os formatos ISO para date, timetz, time, timestamptz e timestamp. Ele para no primeiro formato que corresponde e emite o tipo de dados correspondente.

O método datetime(template) Determina o tipo de dados de resultado de acordo com os campos usados ​​na cadeia de caracteres de modelo fornecida.

Os métodos datetime() e datetime(template) usam as mesmas regras de análise sintática que a função SQL to_timestamp usa (veja a Seção 9.8), Com três exceções. Em primeiro lugar, estes métodos não permitem padrões de modelo sem correspondência. Em segundo lugar, apenas os seguintes separadores são permitidos na cadeia de caracteres de modelo: o sinal de menos, ponto, barra, vírgula, apóstrofo, ponto e vírgula, dois pontos e espaço. Em terceiro lugar, os separadores na cadeia de caracteres do modelo devem corresponder exatamente à cadeia de caracteres de entrada.

Caso seja necessário comparar diferentes tipos de dados de data e hora, é aplicada uma conversão implícita. Um valor do tipo de dados date pode ser convertido para o tipo de dados timestamp ou timestamptz, Um valor do tipo de dados timestamp pode ser convertido para o tipo de dados timestamptz e um valor do tipo de dados time pode ser convertido para o tipo de dados timetz. Entretanto, todas estas conversões, exceto a primeira, dependem da configuração corrente de TimeZone , e, portanto, só pode ser executada em funções para o tipo de dados jsonpath que levam em consideração a zona horária. Da mesma forma, outros métodos relacionados a data e hora que convertem cadeias de caracteres em tipos de dados de data e hora também realizam esta conversão, o que pode envolver a configuração corrente de TimeZone. Portanto, estas conversões também só podem ser realizadas dentro de funções para o tipo de dados jsonpath que levam em consideração a zona horária.

A Tabela 9.53 descreve os elementos de expressão de filtro disponíveis.

Tabela 9.53. Elementos de expressão de filtro para o tipo de dados jsonpath

Predicado/Valor

Descrição

Exemplo(s)

value == valueboolean

Comparação de igualdade (este e os outros operadores de comparação funcionam em todos os valores escalares JSON)

jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == 1)')[1, 1]

jsonb_path_query_array('[1, "a", 1, 3]', '$[*] ? (@ == "a")')["a"]

value != valueboolean

value <> valueboolean

Comparação de não igualdade

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

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

value < valueboolean

Comparação menor-que

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

value <= valueboolean

Comparação menor-que-ou-igual

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

value > valueboolean

Comparação maior-que

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

value >= valueboolean

Comparação maior-que-ou-igual

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

trueboolean

Constante JSON true

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

falseboolean

Constante JSON false

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

nullvalue

Constante JSON null (note que, diferentemente do SQL, a comparação com null funciona normalmente)

jsonb_path_query('[{"name": "Mary", "job": null}, {"name": "Michael", "job": "driver"}]', '$[*] ? (@.job == null) .name')"Mary"

boolean && booleanboolean

AND booleano

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

boolean || booleanboolean

OR booleano

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

! booleanboolean

NOT booleano

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

boolean is unknownboolean

Testa se a condição booleana é unknown.

jsonb_path_query('[-1, 2, 7, "foo"]', '$[*] ? ((@ > 0) is unknown)')"foo"

string like_regex string [ flag string ] → boolean

Testa se o primeiro operando corresponde à expressão regular fornecida pelo segundo operando, opcionalmente com as modificações descritas pelos caracteres da cadeia de caracteres flag (veja a Seção 9.16.2.4).

jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c")')["abc", "abdacb"]

jsonb_path_query_array('["abc", "abd", "aBdC", "abdacb", "babc"]', '$[*] ? (@ like_regex "^ab.*c" flag "i")')["abc", "aBdC", "abdacb"]

string starts with stringboolean

Testa se o segundo operando é uma sub-cadeia de caracteres no início do primeiro operando.

jsonb_path_query('["John Smith", "Mary Stone", "Bob Johnson"]', '$[*] ? (@ starts with "John")')"John Smith"

exists ( path_expression )boolean

Testa se a expressão de caminho corresponde a pelo menos um item SQL/JSON. Retorna unknown se a expressão de caminho resultar em erro; o segundo exemplo usa isto para evitar um erro de no-such-key (não-existe-tal-chave) no modo estrito.

jsonb_path_query('{"x": [1, 2], "y": [2, 4]}', 'strict $.* ? (exists (@ ? (@[*] > 2)))')[2, 4]

jsonb_path_query_array('{"value": 41}', 'strict $ ? (exists (@.name)) .name')[]


9.16.2.4. Expressões regulares SQL/JSON #

As expressões de caminho SQL/JSON permitem a correspondência de texto com uma expressão regular com o filtro like_regex. Por exemplo, a seguinte consulta de caminho SQL/JSON faz a correspondência, sem distinção entre letras maiúsculas e minúsculas, de todas as cadeias de caracteres em uma matriz que começam com uma vogal em inglês:

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

A cadeia de caracteres opcional flag pode incluir um ou mais dos caracteres: i para correspondência que não diferencia letras maiúsculas de minúsculas, m para permitir ^ e $ corresponderem em novas linhas; s para permitir . corresponder a uma nova linha; e q para delimitar todo o padrão (reduzindo o comportamento para uma simples correspondência de sub-cadeia de caracteres).

O padrão SQL/JSON pega emprestado sua definição para expressões regulares do operador LIKE_REGEX, que por sua vez usa o padrão XQuery. No momento o PostgreSQL não oferece suporte ao operador LIKE_REGEX. Portanto, o filtro like_regex é implementado usando o mecanismo de expressão regular POSIX descrito na Seção 9.7.3. Isto leva a várias discrepâncias menores do comportamento SQL/JSON padrão, que estão catalogadas na Seção 9.7.3.8. Note, no entanto, que as incompatibilidades de letras de sinalizador descritas lá não se aplicam a SQL/JSON, porque as letras de sinalizador XQuery são traduzidas para corresponder ao que o mecanismo POSIX espera.

Tenha em mente que o argumento contendo o padrão de like_regex é um literal cadeia de caracteres de caminho JSON, escrito segundo as regras fornecidas na Seção 8.14.7. Isto significa, em particular, que quaisquer contrabarras que se deseja usar na expressão regular devem ser duplicadas. Por exemplo, para corresponder aos valores cadeia de caracteres do documento raiz que contêm apenas dígitos:

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

9.16.3. Funções de consulta de SQL/JSON #

As funções de consulta SQL/JSON JSON_EXISTS(), JSON_QUERY() e JSON_VALUE() descritas na Tabela 9.54 podem ser usadas para consultar documentos JSON. Cada uma destas funções aplica uma expressão de caminho path_expression (uma consulta de caminho SQL/JSON) a um item de contexto context_item (o documento). Veja a Seção 9.16.2 para obter mais detalhes sobre o que a path_expression pode conter. A path_expression também pode fazer referência a variáveis, cujos valores são especificados com seus respectivos nomes na cláusula PASSING que tem suporte por cada função. context_item pode ser um valor do tipo de dados jsonb ou uma cadeia de caracteres que pode ser convertida com sucesso para o tipo de dados jsonb.

Tabela 9.54. Funções de consulta de SQL/JSON

Assinatura da função

Descrição

Exemplo(s)

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

  • Retorna verdade se a path_expression SQL/JSON aplicada ao context_item produzir algum item, falso caso contrário.

  • A cláusula ON ERROR especifica o comportamento a ser seguido caso ocorra algum erro durante a avaliação da expressão de caminho path_expression. Especificar ERROR fará com que seja gerado um erro com a mensagem apropriada. Outras opções incluem retornar os valores do tipo de dados boolean FALSE ou TRUE, ou o valor UNKNOWN, que na verdade é um valor NULL do SQL. O comportamento padrão quando não é especificada nenhuma cláusula ON ERROR, é retornar o valor do tipo de dados boolean FALSE.

Exemplos:

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

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

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

ERRO:  O índice da matriz jsonpath está fora dos limites

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

  • Retorna o resultado da aplicação da expressão de caminho path_expression SQL/JSON ao item de contexto context_item.

  • Por padrão, o resultado é retornado como um valor do tipo de dados jsonb, embora a cláusula RETURNING possa ser usada para retornar algum outro tipo de dados que possa ser convertido com sucesso.

  • Se a expressão do caminho puder retornar vários valores, pode ser necessário encapsular estes valores usando a cláusula WITH WRAPPER para criar uma cadeia de caracteres JSON válida, porque o comportamento padrão é não encapsulá-los, como se tivesse sido especificado WITHOUT WRAPPER. A cláusula WITH WRAPPER é tomada por padrão como WITH UNCONDITIONAL WRAPPER, significando que até mesmo um único valor de resultado será encapsulado. Para aplicar o encapsulamento somente quando estiverem presentes vários valores, deve ser especificado WITH CONDITIONAL WRAPPER. A obtenção de múltiplos valores no resultado será tratada como um erro se for especificada a opção WITHOUT WRAPPER.

  • Se o resultado for uma cadeia de caracteres escalar, por padrão o valor retornado estará entre aspas, tornando-o um valor JSON válido. Isto pode ser explicitado especificando KEEP QUOTES. Inversamente, as aspas podem ser omitidas especificando OMIT QUOTES. Para garantir que o resultado seja um valor JSON válido, não é possível especificar OMIT QUOTES quando WITH WRAPPER também for especificado.

  • A cláusula ON EMPTY especifica o comportamento a ser adotado caso a avaliação da expressão de caminho path_expression resulte em um conjunto vazio. A cláusula ON ERROR especifica o comportamento a ser adotado caso ocorra um erro durante a avaliação da expressão de caminho path_expression, ao converter o valor do resultado para o tipo de dados de RETURNING, ou ao avaliar a expressão ON EMPTY se a avaliação da expressão de caminho path_expression retornar um conjunto vazio.

  • Tanto para ON EMPTY quanto para ON ERROR, especificar ERROR fará com que seja gerado um erro com a mensagem apropriada. Outras opções incluem retornar o valor NULL do SQL ou uma matriz vazia (EMPTY [ARRAY]), ou um objeto vazio (EMPTY OBJECT), ou uma expressão especificada pelo usuário (DEFAULT expression) que pode ser convertida para o tipo de dados jsonb ou para o tipo de dados especificado em RETURNING. O padrão, quando não é especificado nem ON EMPTY nem ON ERROR, é retornar o valor NULL do SQL.

Exemplos:

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

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

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

ERRO:  matriz mal formada: "[1, 2]"
DETALHE:  Faltando "]" após as dimensões da matriz.

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

  • Retorna o resultado da aplicação da expressão de caminho SQL/JSON path_expression ao item de contexto context_item.

  • A função JSON_VALUE() deve ser usada somente se o valor extraído for um único item escalar SQL/JSON; a obtenção de múltiplos valores será tratada como um erro. Se for esperado que o valor extraído seja um objeto ou uma matriz, deve ser usada a função JSON_QUERY em vez desta função.

  • Por padrão, o resultado, que deve ser um único valor escalar, é retornado como um valor do tipo de dados text. embora a cláusula RETURNING possa ser usada para retornar algum outro tipo de dados que possa ser convertido com sucesso.

  • As cláusulas ON ERROR e ON EMPTY possuem semântica semelhante à mencionada na descrição da função JSON_QUERY, exceto que o conjunto de valores retornados em vez de gerar um erro é diferente.

  • Note que as cadeias de caracteres escalares retornadas pela função JSON_VALUE sempre removem as aspas, o que equivale a especificar OMIT QUOTES na função JSON_QUERY.

Exemplos:

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

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

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

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


Nota

A expressão context_item é convertida para o tipo de dados jsonb por meio de uma conversão implícita, caso a expressão já não seja do tipo de dados jsonb. Note, no entanto, que quaisquer erros de análise sintática que ocorram durante esta conversão são reportados incondicionalmente, ou seja, não são tratados de acordo com a cláusula ON ERROR (especificada ou implícita).

Nota

A função JSON_VALUE() irá retornar o valor NULL do SQL se path_expression retornar o valor null do JSON, enquanto a função JSON_QUERY() irá retornar o valor null do JSON tal como se encontra.

9.16.4. JSON_TABLE #

A função JSON_TABLE é uma função SQL/JSON que consulta dados JSON e apresenta os resultados como uma visão relacional, que pode ser acessada como uma tabela SQL comum. A função JSON_TABLE pode ser usada dentro da cláusula FROM das instruções SELECT, UPDATE ou DELETE e como fonte de dados em uma instrução MERGE.

Tomando dados JSON como entrada, a função JSON_TABLE usa uma expressão de caminho JSON para extrair uma parte dos dados fornecidos para usar como um padrão de linha para a visão construída. Cada valor SQL/JSON fornecido pelo padrão de linha serve como fonte para uma linha separada na visão construída.

Para dividir o padrão de linhas em colunas, a função JSON_TABLE fornece a cláusula COLUMNS que define o esquema da visão criada. Para cada coluna, pode ser especificada uma expressão de caminho JSON separada para ser avaliada em relação ao padrão da linha, a fim de obter um valor SQL/JSON que se tornará o valor da coluna especificada em uma determinada linha de saída.

Os dados JSON armazenados em um nível aninhado do padrão de linha podem ser extraídos usando a cláusula NESTED PATH (caminho aninhado). Cada cláusula NESTED PATH pode ser usada para gerar uma ou mais colunas usando os dados de um nível aninhado do padrão de linha. Estas colunas podem ser especificadas usando uma cláusula COLUMNS, que é semelhante à cláusula COLUMNS de nível superior. As linhas construídas a partir de NESTED COLUMNS são chamadas de child rows (linhas filhas) e são unidas à linha construída a partir das colunas especificadas na cláusula mãe COLUMNS para obter a linha na visão final. As próprias colunas filhas podem conter uma especificação de NESTED PATH, permitindo assim extrair dados localizados em níveis de aninhamento arbitrários. As colunas produzidas por múltiplos NESTED PATH no mesmo nível são consideradas siblings (irmãs) umas das outras e suas linhas, após serem unidas à linha mãe, são combinadas usando UNION.

As linhas produzidas pela função JSON_TABLE são unidas lateralmente à linha que as gerou, portanto, não é necessário unir explicitamente a visão construída com a tabela original que contém os dados JSON.

A sintaxe é:

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


one json_table_column é:

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

Cada elemento da sintaxe é descrito com mais detalhes abaixo.

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

context_item especifica o documento de entrada a ser consultado, path_expression é uma expressão de caminho SQL/JSON que define a consulta, e json_path_name é um nome opcional para path_expression. A cláusula opcional PASSING fornece valores de dados para as variáveis ​​mencionadas em path_expression. O resultado da avaliação dos dados de entrada usando os elementos mencionados anteriormente é chamado de row pattern (padrão de linha), que é usado como fonte para os valores das linhas na visão construída.

COLUMNS ( json_table_column [, ...] )

A cláusula COLUMNS que define o esquema da visão construída. Nesta cláusula, é possível especificar que cada coluna seja preenchida com um valor SQL/JSON obtido pela aplicação de uma expressão de caminho JSON ao padrão de linha. json_table_column possui as seguintes variantes:

name FOR ORDINALITY

Adiciona uma coluna de ordinalidade que fornece numeração sequencial de linhas a partir de 1. Cada NESTED PATH (veja abaixo) obtém seu próprio contador para quaisquer colunas de ordinalidade aninhadas.

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

Insere o valor SQL/JSON obtido pela aplicação de path_expression ao padrão de linha na linha de saída da visão, após convertê-lo para o type especificado.

Especificar FORMAT JSON deixa explícito que é esperado que o valor seja um objeto do tipo de dados json válido. Só faz sentido especificar FORMAT JSON se type for um entre bpchar, bytea, character varying, name, json, jsonb, text, ou um domínio sobre estes tipos de dados.

Opcionalmente, podem ser especificadas as cláusulas WRAPPER e QUOTES para formatar a saída. Note que especificar OMIT QUOTES se sobrepõe a FORMAT JSON se este também for especificado, porque literais sem aspas não constituem valores do tipo de dados json válidos.

Opcionalmente, podem ser usadas as cláusulas ON EMPTY e ON ERROR para especificar se deve ser gerados um erro ou retornado o valor especificado quando o resultado da avaliação do caminho JSON estiver vazio, e quando ocorrer um erro durante a avaliação do caminho JSON ou ao converter o valor SQL/JSON para o tipo de dados especificado, respectivamente. O padrão para ambos é retornar o valor NULL.

Nota

Esta cláusula é internamente transformada e tem a mesma semântica das funções JSON_VALUE e JSON_QUERY. Este último caso se aplica se o tipo de dados especificado não for um tipo de dados escalar, ou se uma das cláusulas FORMAT JSON, WRAPPER ou QUOTES estiver presente.

name type EXISTS [ PATH path_expression ]

Insere o valor booleano obtido pela aplicação de path_expression ao padrão de linha na linha de saída da visão, após convertê-la para o type especificado.

O valor corresponde à aplicação da expressão PATH ao padrão da linha, retornando valores ou não.

O type especificado deve possuir uma conversão a partir do tipo de dados boolean.

Opcionalmente, pode ser usada a cláusula ON ERROR para especificar se deve ser gerado um erro ou retornado o valor especificado quando for encontrado um erro durante a avaliação do arquivo JSON ou durante a conversão do valor SQL/JSON para o tipo de dados especificado. O padrão é retornar o valor booleano FALSE.

Nota

Esta cláusula é transformada internamente e tem a mesma semântica que JSON_EXISTS.

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

Extrai valores SQL/JSON de níveis aninhados do padrão de linha, gera uma ou mais colunas conforme definido pela subcláusula COLUMNS e insere os valores SQL/JSON extraídos nessas colunas. A expressão json_table_column na subcláusula COLUMNS usa a mesma sintaxe da cláusula COLUMNS mãe.

A sintaxe NESTED PATH é recursiva, assim é possível percorrer vários níveis aninhados especificando várias subcláusulas NESTED PATH umas dentro das outras. Permite desaninhar a hierarquia de objetos e matrizes JSON em uma única invocação de função, em vez de encadear várias expressões JSON_TABLE em uma instrução SQL.

Nota

Em cada variante de json_table_column descrita acima, se a cláusula PATH for omitida, será usada a expressão de caminho $.name, onde name é o nome da coluna fornecido.

AS json_path_name

A cláusula opcional json_path_name serve como identificador para a path_expression fornecida. O nome deve ser único e distinto dos nomes das colunas.

{ ERROR | EMPTY } ON ERROR

Pode ser usada a cláusula opcional ON ERROR para especificar como lidar com erros ao avaliar a path_expression de nível superior. Deve ser usado ERROR se for desejado que sejam gerados erros ou EMPTY para retornar uma tabela vazia, ou seja, uma tabela contendo 0 linhas. Note que esta cláusula não afeta os erros que ocorrem ao avaliar colunas, cujo comportamento depende de a cláusula ON ERROR estar especificada para uma determinada coluna.

Exemplos

Nos exemplos que a seguir, será utilizada a seguinte tabela contendo dados JSON:

CREATE TABLE my_films ( js jsonb );

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

A consulta a seguir mostra como usar a função JSON_TABLE para transformar os objetos JSON da tabela my_films em uma visão contendo colunas para as chaves kind, title e director presentes no JSON original, juntamente com uma coluna de ordinalidade:

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

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

A seguir, é apresentada uma versão modificada da consulta acima para mostrar o uso de argumentos PASSING no filtro especificado na expressão do caminho JSON de nível superior e as várias opções para as colunas individuais:

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

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

A seguir é apresentada uma versão modificada da consulta acima para mostrar o uso de NESTED PATH para preencher as colunas title e director, ilustrando como elas são unidas às colunas mãe id e kind:

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

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

A seguir é apresentada a mesma consulta, porém sem o filtro no caminho raiz:

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

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

A seguir é apresentada outra consulta usando um objeto do tipo de dados JSON diferente como entrada. Ela mostra a junção de irmãos (sibling join/UNION) entre os caminhos aninhados (NESTED) $.movies[*] e $.books[*], e também o uso da coluna FOR ORDINALITY nos níveis aninhados (NESTED) (colunas movie_id, book_id e author_id):

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

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