Ustaw nazwy atrybutów podczas tworzenia JSON za pomocą row_to_json


24

Czy można zmienić nazwy domyślne f1, f2, f3...przy użyciu row_to_jsonfunkcji tylko dla niektórych kolumn?

potrafię

row_to_json(customers)

powracający

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

Ale jeśli chcę tylko nazwy bez id_customer, muszę użyć

row_to_json(row(first_name, last_name))

a potem dostaję

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

Chciałbym uzyskać ten wynik z domyślnymi nazwami kolumn lub własnymi. Wiem, że mogę stworzyć własny typ kompozytu i użyć go

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

ale czy nie można tego zrobić poprawnie w zapytaniu bez utworzenia tego typu?


1
Zobacz także: odniesienie 1 i odniesienie 2 podobne
— MikeM

Odpowiedzi:


17

Wspólne wyrażenie tabelowe pozwala jawnie określać aliasy, nie tylko dla CTE, ale dla jego kolumn.

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

Różni się to od przykładu @ dezso, ponieważ nie stosuje się go col AS aliasdla każdej kolumny na SELECTliście; aliasuje nazwy kolumn w aliasie tabeli CTE.

Użyłem VALUESwyrażenia jako podzapytania, ale możesz użyć SELECTdowolnego, co chcesz; Chodzi o to, że wszelkie aliasy kolumn, które są udostępniane lub zakładane w podzapytaniu, można zastąpić w definicji CTE, określając listę nazw kolumn.

Możesz zrobić to samo w podzapytaniu, ponownie zamiast używać AS alias:

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

To nie działa ROWbezpośrednio z wyrażeniem; możesz rzucić tylko ROWna konkretny typ, nie możesz go aliasować.

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);

Czy jest jakaś różnica (oprócz stylu i / lub czytelności) między naszymi rozwiązaniami (użytkowanie, wydajność itp.)?
— dezso

@dezso Nie, i prawdopodobnie powinienem właśnie opublikować komentarz. Przepraszam.
— Craig Ringer

Myślę, że to jest OK. Poparłem nawet twoją odpowiedź, ponieważ zawiera przydatne informacje, których moja nie ma.
— dezso,

Czy istnieje składnia dynamicznego pobierania aliasów kolumn? Wyciągam ze schematu EAV (wartość atrybutu bytu), w którym pożądane nazwy kluczy są również wybierane z kolumny attribute.name.
— Chris

@Chris Potrzebujesz bardziej wyrafinowanych funkcji JSON w 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

zrobi co chcesz bez wpływu na wydajność (i nie jest zbyt gadatliwy):

  id  |   first_last                                |   age
------+---------------------------------------------+---------
  1   | {"fisrt_name": "John", "last_name": "Smit"} |   34

4
Ta odpowiedź to klejnot.
— tiffon

Dziękuję bardzo, że uratowałeś moje popołudnie, szkoda, że ​​nie jest to cytowany przykład w interfejsie API PostgreSQL. Wiedziałem, że to możliwe
— jlandercy

9

Możesz zrobić coś takiego:

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

(Oczywiście to samo można osiągnąć za pomocą

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

ale ten pierwszy był bardziej czytelny).

W WITHczęści możesz budować w locie rzędy dowolnej struktury.


Aby połączyć nie-jsonb z jsonb :: SELECT row_to_json (r. *) FROM (SELECT c1, c2 :: jsonb FROM us_ca_monterey_aoc.test) as r
— Andrew Scott Evans

9

Możesz użyć 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;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.