Eu gostaria que o PostgreSQL retornasse o resultado de uma consulta como uma matriz JSON. Dado
create table t (a int primary key, b text);
insert into t values (1, 'value1');
insert into t values (2, 'value2');
insert into t values (3, 'value3');
Eu gostaria de algo parecido com
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
ou
{"a":[1,2,3], "b":["value1","value2","value3"]}
(na verdade, seria mais útil conhecer os dois). Eu tentei algumas coisas como
select row_to_json(row) from (select * from t) row;
select array_agg(row) from (select * from t) row;
select array_to_string(array_agg(row), '') from (select * from t) row;
E sinto que estou perto, mas na verdade não existe. Devo procurar outra documentação, exceto a 9.15. Funções e operadores JSON ?
A propósito, não tenho certeza da minha ideia. Essa é uma decisão usual de design? Meu pensamento é que eu poderia, é claro, pegar o resultado (por exemplo) da primeira das 3 consultas acima e manipulá-lo levemente no aplicativo antes de servi-lo ao cliente, mas se o PostgreSQL puder criar diretamente o objeto JSON final diretamente, seria mais simples, porque ainda não incluí nenhuma dependência em nenhuma biblioteca JSON no meu aplicativo.
fonte
Respostas:
TL; DR
para uma matriz de objetos JSON e
para um objeto JSON de matrizes.
Lista de objetos
Esta seção descreve como gerar uma matriz de objetos JSON, com cada linha sendo convertida em um único objeto. O resultado fica assim:
9.3 e superior
A
json_agg
função produz esse resultado imediatamente. Ele automaticamente descobre como converter sua entrada em JSON e a agrega em uma matriz.Não existe
jsonb
(introduzida na 9.4) versão dojson_agg
. Você pode agregar as linhas em uma matriz e depois convertê-las:ou combine
json_agg
com um elenco:Meus testes sugerem que agregá-los em uma matriz primeiro é um pouco mais rápido. Eu suspeito que isso ocorre porque o elenco precisa analisar o resultado JSON inteiro.
9.2
9.2 não possui as funções
json_agg
outo_json
, portanto, você precisa usar as mais antigasarray_to_json
:Opcionalmente, você pode incluir uma
row_to_json
chamada na consulta:Isso converte cada linha em um objeto JSON, agrega os objetos JSON como uma matriz e, em seguida, converte a matriz em uma matriz JSON.
Não consegui discernir nenhuma diferença significativa de desempenho entre os dois.
Objeto de listas
Esta seção descreve como gerar um objeto JSON, com cada chave sendo uma coluna na tabela e cada valor sendo uma matriz dos valores da coluna. É o resultado que se parece com isso:
9.5 e superior
Podemos aproveitar a
json_build_object
função:Você também pode agregar as colunas, criando uma única linha e convertê-las em um objeto:
Observe que o alias das matrizes é absolutamente necessário para garantir que o objeto tenha os nomes desejados.
Qual é o mais claro é uma questão de opinião. Se estiver usando a
json_build_object
função, recomendo colocar um par de chave / valor em uma linha para melhorar a legibilidade.Você também pode usar
array_agg
no lugar dejson_agg
, mas meus testes indicam quejson_agg
é um pouco mais rápido.Não há
jsonb
versão dajson_build_object
função. Você pode agregar em uma única linha e converter:Ao contrário das outras consultas para esse tipo de resultado,
array_agg
parece ser um pouco mais rápido ao usarto_jsonb
. Eu suspeito que isso se deva à sobrecarga de análise e validação do resultado JSON dejson_agg
.Ou você pode usar um elenco explícito:
A
to_jsonb
versão permite evitar o elenco e é mais rápida, de acordo com meus testes; novamente, suspeito que isso se deva à sobrecarga de analisar e validar o resultado.9.4 e 9.3
A
json_build_object
função era nova na 9.5, portanto, você precisa agregar e converter em um objeto nas versões anteriores:ou
dependendo se você deseja
json
oujsonb
.(9.3 não possui
jsonb
.)9.2
No 9.2, nem
to_json
existe. Você deve usarrow_to_json
:Documentação
Encontre a documentação para as funções JSON nas funções JSON .
json_agg
está na página de funções agregadas .Projeto
Se o desempenho for importante, verifique se suas consultas são comparadas com seu próprio esquema e dados, em vez de confiar nos meus testes.
Se é um bom design ou não, realmente depende da sua aplicação específica. Em termos de manutenção, não vejo nenhum problema específico. Isso simplifica o código do seu aplicativo e significa que há menos para manter nessa parte do aplicativo. Se o PG pode fornecer exatamente o resultado que você precisa imediatamente, a única razão pela qual posso pensar em não usá-lo seria considerações de desempenho. Não reinvente a roda e tudo.
Nulos
As funções agregadas geralmente retornam
NULL
quando operam sobre zero linhas. Se isso for uma possibilidade, convém usá-loCOALESCE
para evitá-los. Alguns exemplos:Ou
Agradecemos a Hannes Landeholm por apontar isso
fonte
to_json
vez derow_to_json
earray_to_json
SELECT json_agg((column1, column2, ...)) FROM t
- observe os colchetes extras. Isso pode não ser óbvio "pronto para uso".Além disso, se você desejar o campo selecionado da tabela e agregado, em seguida, como matriz.
O resultado virá.
fonte