Me gustaría que PostgreSQL devuelva el resultado de una consulta como una matriz JSON. Dado
create table t (a int primary key, b text);
insert into t values (1, 'value1');
insert into t values (2, 'value2');
insert into t values (3, 'value3');
Me gustaria algo similar a
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
o
{"a":[1,2,3], "b":["value1","value2","value3"]}
(En realidad, sería más útil conocer ambos). He intentado algunas cosas como
select row_to_json(row) from (select * from t) row;
select array_agg(row) from (select * from t) row;
select array_to_string(array_agg(row), '') from (select * from t) row;
Y siento que estoy cerca, pero en realidad no. ¿Debo estar mirando otra documentación, excepto 9.15. ¿Funciones y operadores JSON ?
Por cierto, no estoy seguro de mi idea. ¿Es esta una decisión de diseño habitual? Mi opinión es que, por supuesto, podría tomar el resultado (por ejemplo) de la primera de las 3 consultas anteriores y manipularlo ligeramente en la aplicación antes de entregarlo al cliente, pero si PostgreSQL puede crear el objeto JSON final directamente, sería más simple, porque todavía no he incluido ninguna dependencia en ninguna biblioteca JSON en mi aplicación.
fuente
Respuestas:
TL; DR
para una matriz JSON de objetos, y
para un objeto JSON de matrices.
Lista de objetos
Esta sección describe cómo generar una matriz JSON de objetos, con cada fila convertida en un solo objeto. El resultado se ve así:
9.3 y hasta
La
json_agg
función produce este resultado fuera de la caja. Automáticamente descubre cómo convertir su entrada en JSON y la agrega en una matriz.No hay una
jsonb
versión (introducida en 9.4) dejson_agg
. Puede agregar las filas en una matriz y luego convertirlas:o combinar
json_agg
con un yeso:Mi prueba sugiere que agregarlos primero en una matriz es un poco más rápido. Sospecho que esto se debe a que el elenco tiene que analizar todo el resultado JSON.
9.2
9.2 no tiene las funciones
json_agg
oto_json
, por lo que debe usar las anterioresarray_to_json
:Opcionalmente, puede incluir una
row_to_json
llamada en la consulta:Esto convierte cada fila en un objeto JSON, agrega los objetos JSON como una matriz y luego convierte la matriz en una matriz JSON.
No pude discernir ninguna diferencia de rendimiento significativa entre los dos.
Objeto de listas
Esta sección describe cómo generar un objeto JSON, cada clave es una columna en la tabla y cada valor es una matriz de los valores de la columna. Es el resultado que se ve así:
9.5 y más
Podemos aprovechar la
json_build_object
función:También puede agregar las columnas, crear una sola fila y luego convertirla en un objeto:
Tenga en cuenta que el alias de las matrices es absolutamente necesario para garantizar que el objeto tenga los nombres deseados.
Cuál es más claro es una cuestión de opinión. Si usa la
json_build_object
función, le recomiendo poner un par clave / valor en una línea para mejorar la legibilidad.También podría usarlo
array_agg
en lugar dejson_agg
, pero mis pruebas indican quejson_agg
es un poco más rápido.No hay una
jsonb
versión de lajson_build_object
función. Puede agregar en una sola fila y convertir:A diferencia de otras consultas para este tipo de resultado,
array_agg
parece ser un poco más rápido cuando se usato_jsonb
. Sospecho que esto se debe al análisis y validación generales del resultado JSON dejson_agg
.O puede usar un reparto explícito:
La
to_jsonb
versión le permite evitar el reparto y es más rápido, según mis pruebas; De nuevo, sospecho que esto se debe a la sobrecarga de analizar y validar el resultado.9.4 y 9.3
La
json_build_object
función era nueva en 9.5, por lo que debe agregar y convertir a un objeto en versiones anteriores:o
dependiendo de si quieres
json
ojsonb
.(9.3 no tiene
jsonb
)9.2
En 9.2, ni siquiera
to_json
existe. Debes usarrow_to_json
:Documentación
Encuentre la documentación para las funciones JSON en las funciones JSON .
json_agg
está en la página de funciones agregadas .Diseño
Si el rendimiento es importante, asegúrese de comparar sus consultas con su propio esquema y datos, en lugar de confiar en mis pruebas.
Si es un buen diseño o no, realmente depende de su aplicación específica. En términos de mantenibilidad, no veo ningún problema en particular. Simplifica el código de su aplicación y significa que hay menos para mantener en esa parte de la aplicación. Si PG puede darle exactamente el resultado que necesita de inmediato, la única razón por la que se me ocurre no usarlo sería por consideraciones de rendimiento. No reinventes la rueda y todo.
Nulos
Las funciones agregadas generalmente devuelven
NULL
cuando operan sobre filas cero. Si esto es una posibilidad, puede utilizarCOALESCE
para evitarlos. Un par de ejemplos:O
Gracias a Hannes Landeholm por señalar esto
fuente
to_json
lugar derow_to_json
yarray_to_json
SELECT json_agg((column1, column2, ...)) FROM t
, observe los corchetes adicionales. Esto puede no ser obvio "fuera de la caja".Además, si desea seleccionar el campo de la tabla y agregarlo como matriz.
El resultado vendrá.
fuente