Tetapkan nama menjadi atribut saat membuat JSON dengan row_to_json

24

Apakah mungkin untuk mengganti f1, f2, f3...nama nama standar saat menggunakan row_to_jsonfungsi hanya untuk beberapa kolom?

dapat saya lakukan

row_to_json(customers)

kembali

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

Tetapi jika saya hanya ingin nama tanpa id_customer, saya harus menggunakan

row_to_json(row(first_name, last_name))

dan kemudian saya dapatkan

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

Dan saya ingin mendapatkan hasil ini dengan nama kolom default atau nama saya sendiri. Saya tahu saya bisa membuat tipe dan penggunaan komposit sendiri

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

tetapi apakah tidak mungkin untuk melakukannya dengan benar dalam permintaan tanpa membuat jenis itu?

boobiq
sumber
1
Juga, lihat: referensi 1 dan referensi 2 untuk serupa
MikeM

Jawaban:

17

Ekspresi tabel yang umum memungkinkan Anda untuk menentukan alias secara eksplisit, tidak hanya untuk CTE tetapi untuk kolomnya.

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

Ini berbeda dengan contoh @ dezso karena tidak digunakan col AS aliasuntuk setiap col dalam SELECTdaftar; alias nama kolom dalam alias tabel CTE.

Saya telah menggunakan VALUESekspresi sebagai subquery tetapi Anda dapat menggunakan SELECTapa pun yang Anda suka; intinya adalah bahwa apa pun alias kolom yang disediakan atau diasumsikan dalam subquery dapat ditimpa dalam definisi CTE dengan menetapkan daftar nama-kolom.

Anda bisa melakukan hal yang sama di subquery, lagi daripada menggunakan AS alias:

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

Ini tidak bekerja dengan ROWekspresi secara langsung; Anda hanya bisa melemparkan ROWke tipe beton, Anda tidak bisa menamainya.

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
sumber
Apakah ada perbedaan (terlepas dari gaya dan / atau keterbacaan) antara solusi kami (penggunaan, kinerja, dll.)?
dezso
@dezso Tidak, dan saya mungkin seharusnya mengirim komentar. Maaf.
Craig Ringer
Saya pikir ini baik-baik saja. Saya bahkan membatalkan jawaban Anda karena itu berisi informasi berguna yang tidak saya miliki.
dezso
Apakah ada sintaks untuk mendapatkan alias alias kolom secara dinamis? Saya menarik dari skema EAV (nilai atribut entitas) di mana nama kunci yang diinginkan juga dipilih dari kolom attribute.name.
Chris
@ Chris Anda membutuhkan fungsi json yang lebih canggih di 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

akan melakukan apa yang Anda inginkan tanpa dampak kinerja apa pun (dan tidak terlalu bertele-tele):

  id  |   first_last                                |   age
------+---------------------------------------------+---------
  1   | {"fisrt_name": "John", "last_name": "Smit"} |   34
Anatoly Ressin
sumber
4
Jawaban ini adalah permata.
tiffon
Terima kasih banyak, Anda telah menyelamatkan sore saya, sayang sekali ini bukan contoh yang dikutip di PostgreSQL API. Saya tahu itu mungkin
jlandercy
9

Anda dapat melakukan sesuatu seperti ini:

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

(Tentu saja, hal yang sama dapat dicapai dengan

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

tapi saya menemukan yang pertama lebih mudah dibaca.)

Pada WITHbagian ini Anda dapat membuat baris struktur apa saja dengan cepat.

dezso
sumber
Untuk menggabungkan non-jsonb dengan jsonb :: SELECT row_to_json (r. *) FROM (SELECT c1, c2 :: jsonb FROM us_ca_monterey_aoc.test) sebagai r
Andrew Scott Evans
9

Anda bisa menggunakannya 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
sumber