Задать имена атрибутам при создании JSON с row_to_json

24

Можно ли переименовать f1, f2, f3...имена по умолчанию при использовании row_to_jsonфункции только для некоторых столбцов?

я могу сделать

row_to_json(customers)

возврате

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

Но если я хочу только имена без id_customer, я должен использовать

row_to_json(row(first_name, last_name))

и тогда я получаю

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

И я хотел бы получить этот результат либо с именами столбцов по умолчанию, либо с моими собственными. Я знаю, что могу создать свой собственный составной тип и использовать

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

но разве невозможно сделать это правильно в запросе, не создавая этот тип?

boobiq
источник
1
Также см .: ссылка 1 и ссылка 2 на аналогичные
MikeM

Ответы:

17

Распространенное табличное выражение позволяет явно указывать псевдонимы не только для CTE, но и для его столбцов.

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

Это отличается от примера @ dezso тем, что он не используется col AS aliasдля каждого столбца в SELECTсписке; это псевдоним имен столбцов в псевдониме таблицы CTE.

Я использовал VALUESвыражение как подзапрос, но вы можете использовать SELECTвсе, что вам нравится; Дело в том, что любые псевдонимы столбцов, которые предоставляются или предполагаются в подзапросе, могут быть переопределены в определении CTE, указав имя столбца-списка.

Вы можете сделать то же самое в подзапросе, снова вместо использования AS alias:

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

Это не работает с ROWвыражением напрямую; вы можете привести только ROWк конкретному типу, вы не можете использовать его псевдоним.

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);
Крейг Рингер
источник
Есть ли разница (кроме стиля и / или читабельности) между нашими решениями (использование, производительность и т. Д.)?
Дезсо
@dezso Нет, и я, наверное, должен был просто оставить комментарий. Сожалею.
Крейг Рингер
Я думаю, что это нормально. Я даже проголосовал за ваш ответ, потому что он содержит полезную информацию, а моя нет.
Дезсо
Существует ли синтаксис для динамического получения псевдонимов столбцов? Я извлекаю из схемы EAV (значение атрибута сущности), в которой имена нужных ключей также выбираются из столбца attribute.name.
Крис
@Chris Вам понадобятся более сложные функции JSON в 9.4.
Крейг Рингер
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

будет делать то, что вы хотите, без какого-либо влияния на производительность (и не слишком многословно):

  id  |   first_last                                |   age
------+---------------------------------------------+---------
  1   | {"fisrt_name": "John", "last_name": "Smit"} |   34
Анатолий Рессин
источник
4
Этот ответ является драгоценным камнем.
Tiffon
Большое спасибо, что вы сохранили мой день, очень плохо, что это не цитируемый пример в PostgreSQL API. Я знал, что это было возможно
jlandercy
9

Вы можете сделать что-то вроде этого:

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

(Конечно, то же самое может быть достигнуто с

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

но я нашел первый более читабельным.)

В WITHчасти вы можете построить ряды любой структуры на лету.

Dezso
источник
Конкатенировать не-jsonb с помощью jsonb :: SELECT row_to_json (r. *) FROM (SELECT c1, c2 :: jsonb FROM us_ca_monterey_aoc.test) как r
Эндрю Скотт Эванс
9

Вы можете использовать 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
источник