Configure nomes para atributos ao criar JSON com row_to_json

24

É possível renomear f1, f2, f3...nomes padrão ao usar a row_to_jsonfunção apenas para algumas colunas?

eu posso fazer

row_to_json(customers)

retornando

{"id_customer":2,"first_name":"bla","last_name":"second_bla"}

Mas se eu quero apenas nomes sem id_customer, tenho que usar

row_to_json(row(first_name, last_name))

e então eu recebo

{"f1":"bla","f2":"second_bla"}

E eu gostaria de obter esse resultado com nomes de colunas padrão ou com os meus. Eu sei que posso criar meu próprio tipo composto e usar

row_to_json(row(first_name, last_name))::my_custom_type

mas não é possível fazer isso corretamente na consulta sem criar esse tipo?

boobiq
fonte
11
Veja também: referência 1 e referência 2 para similares #
MikeM

Respostas:

17

Uma expressão de tabela comum permite especificar aliases explicitamente, não apenas para o CTE, mas para suas colunas.

WITH data(col1,col2,cola,colb) AS (
  VALUES (1,2,'fred','bob')
)
SELECT row_to_json(data) FROM data;

Isso é diferente do exemplo do @ dezso, pois ele não usa col AS aliaspara cada coluna em uma SELECTlista; alias os nomes das colunas no alias da tabela CTE.

Eu usei uma VALUESexpressão como subconsulta, mas você pode usar SELECTo que quiser; o ponto é que quaisquer aliases de coluna fornecidos ou assumidos na subconsulta podem ser substituídos na definição CTE, especificando uma lista de nomes de colunas.

Você pode fazer o mesmo em uma subconsulta, novamente, em vez de usar AS alias:

SELECT row_to_json(data) 
FROM (VALUES (1,2,'fred','bob')) data(col1,col2,cola,colb);

Isso não funciona ROWdiretamente com uma expressão; você só pode converter a ROWem um tipo concreto, não pode usar o alias.

regress=> SELECT ROW(1,2,'fred','bob') AS x(a,b,c,d);
ERROR:  syntax error at or near "("
LINE 1: SELECT ROW(1,2,'fred','bob') AS x(a,b,c,d);
Craig Ringer
fonte
Existe alguma diferença (além do estilo e / ou legibilidade) entre nossas soluções (uso, desempenho, etc.)?
Dezso
@ Dezso Não, e eu provavelmente deveria ter postado um comentário. Desculpe.
Craig Ringer
Eu acho que está tudo bem. Eu até votei sua resposta porque ela contém informações úteis que a minha não contém.
Dezso
Existe uma sintaxe para obter os aliases da coluna dinamicamente? Estou usando um esquema EAV (valor do atributo da entidade) em que os nomes de chave desejados também são selecionados na coluna attribute.name.
Chris
@ Chris Você precisará das funções json mais sofisticadas da 9.4.
Craig Ringer
23
select 
   c.id,
   (select row_to_json(_) from (select c.first_name, c.last_name) as _) as first_last,
   c.age
from
   customers as c

fará o que você deseja sem nenhum impacto no desempenho (e não é muito detalhado):

  id  |   first_last                                |   age
------+---------------------------------------------+---------
  1   | {"fisrt_name": "John", "last_name": "Smit"} |   34
Anatoly Ressin
fonte
4
Esta resposta é uma jóia.
tiffon
Muito obrigado você salvou minha tarde, pena que este não é um exemplo citado na API do PostgreSQL. Eu sabia que era possível
jlandercy
9

Você pode fazer algo assim:

WITH r AS (
  SELECT 'bla' AS name1, 'otherbla' AS name2
)
SELECT row_to_json(r.*)
FROM r
;

(Obviamente, o mesmo pode ser alcançado com

SELECT row_to_json(r.*)
FROM (SELECT 'bla' AS name1, 'otherbla' AS name2) r
;

mas achei o primeiro mais legível.)

Na WITHparte, você pode construir linhas de qualquer estrutura em tempo real.

dezso
fonte
Para concatenar non-jsonb com jsonb :: SELECT row_to_json (r. *) FROM (SELECT c1, c2 :: jsonb FROM us_ca_monterey_aoc.test) como r
Andrew Scott Evans
9

Você pode usar json_build_object.

SELECT 
  json_build_object('id', data.customer_id, 'first_name', data.first_name, 'last_name', data.last_name) as your_json
FROM data;
aheuermann
fonte