Establezca nombres en atributos al crear JSON con row_to_json


24

¿Es posible cambiar el nombre de los f1, f2, f3...nombres predeterminados cuando se usa la row_to_jsonfunción solo para algunas columnas?

puedo hacer

row_to_json(customers)

volviendo

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

Pero si solo quiero nombres sin id_customer, tengo que usar

row_to_json(row(first_name, last_name))

y luego me sale

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

Y me gustaría obtener este resultado con los nombres de columna predeterminados o con el mío. Sé que puedo crear mi propio tipo compuesto y usar

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

pero, ¿no es posible hacerlo bien en la consulta sin crear ese tipo?


1
Ver también: referencia 1 y referencia 2 para similares
MikeM

Respuestas:


17

Una expresión de tabla común le permite especificar alias explícitamente, no solo para el CTE sino también para sus columnas.

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

Esto es diferente al ejemplo de @ dezso en que no usa col AS alias para cada columna de una SELECTlista; alias los nombres de columna en el alias de la tabla CTE.

He usado un VALUES expresión como subconsulta, pero puedes usar SELECTlo que quieras; el punto es que cualquier alias de columna que se proporcione o se asuma en la subconsulta puede anularse en la definición de CTE especificando una lista de nombres de columna.

Puede hacer lo mismo en una subconsulta, de nuevo en lugar de usar AS alias:

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

Esto no funciona con una ROWexpresión directamente; solo puedes lanzar un ROWtipo concreto, no puedes usar 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);

¿Hay alguna diferencia (aparte del estilo y / o legibilidad) entre nuestras soluciones (uso, rendimiento, etc.)?
dezso

@dezso No, y probablemente debería haber publicado un comentario. Lo siento.
Craig Ringer

Creo que esto esta bien. Incluso voté por tu respuesta porque contiene información útil que la mía no contiene.
dezso

¿Existe una sintaxis para obtener dinámicamente los alias de columna? Extraigo de un esquema EAV (valor de atributo de entidad) donde los nombres de clave deseados también se seleccionan de la columna atributo.nombre.
Chris

@Chris Necesitarás las funciones json más sofisticadas en 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

hará lo que quiera sin ningún impacto en el rendimiento (y no es demasiado detallado):

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

44
Esta respuesta es una joya.
tiffon

Muchas gracias por salvarme la tarde, lástima que este no sea un ejemplo citado en la API de PostgreSQL. Sabía que era posible
jlandercy

9

Puedes hacer algo como esto:

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

(Por supuesto, lo mismo se puede lograr con

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

pero encontré el primero más legible).

En la WITHparte puedes construir filas de cualquier estructura sobre la marcha.


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

9

Puedes 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;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.