Définissez des noms pour les attributs lors de la création de JSON avec row_to_json

24

Est-il possible de renommer les f1, f2, f3...noms par défaut lorsque vous n'utilisez la row_to_jsonfonction que pour certaines colonnes?

Je peux faire

row_to_json(customers)

de retour

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

Mais si je veux seulement des noms sans id_customer, je dois utiliser

row_to_json(row(first_name, last_name))

et je reçois

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

Et je voudrais obtenir ce résultat avec les noms de colonnes par défaut ou les miens. Je sais que je peux créer mon propre type composite et l'utiliser

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

mais n'est-il pas possible de le faire directement dans la requête sans créer ce type?

boobiq
la source
1
Voir aussi: référence 1 et référence 2 pour similaire
MikeM

Réponses:

17

Une expression de table commune vous permet de spécifier explicitement des alias, non seulement pour le CTE mais pour ses colonnes.

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

Ceci est différent de l'exemple de @ dezso en ce qu'il n'utilise pas col AS aliaspour chaque col d'une SELECTliste; il alias les noms de colonne dans l'alias de table CTE.

J'ai utilisé une VALUESexpression comme sous-requête, mais vous pouvez utiliser ce SELECTque vous voulez; le fait est que les alias de colonne fournis ou supposés dans la sous-requête peuvent être remplacés dans la définition CTE en spécifiant une liste de noms de colonnes.

Vous pouvez faire la même chose dans une sous-requête, à nouveau au lieu d'utiliser AS alias:

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

Cela ne fonctionne pas ROWdirectement avec une expression; vous pouvez uniquement convertir un ROWen un type concret, vous ne pouvez pas l'aliaser.

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
la source
Existe-t-il une différence (hormis le style et / ou la lisibilité) entre nos solutions (utilisation, performances, etc.)?
dezso
@dezso Non, et j'aurais probablement dû poster un commentaire. Désolé.
Craig Ringer
Je pense que c'est OK. J'ai même voté contre votre réponse car elle contient des informations utiles que la mienne ne contient pas.
dezso
Existe-t-il une syntaxe pour obtenir les alias de colonne de manière dynamique? Je tire d'un schéma EAV (valeur d'attribut d'entité) où les noms de clés souhaités sont également sélectionnés dans la colonne attribute.name.
Chris
@Chris Vous aurez besoin des fonctions json plus sophistiquées 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

fera ce que vous voulez sans aucun impact sur les performances (et n'est pas trop verbeux):

  id  |   first_last                                |   age
------+---------------------------------------------+---------
  1   | {"fisrt_name": "John", "last_name": "Smit"} |   34
Anatoly Ressin
la source
4
Cette réponse est un joyau.
tiffon
Merci beaucoup d'avoir sauvé mon après-midi, dommage que ce ne soit pas un exemple cité dans l'API PostgreSQL. Je savais que c'était possible
jlandercy
9

Vous pouvez faire quelque chose comme ça:

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

(Bien sûr, la même chose peut être obtenue avec

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

mais j'ai trouvé l'ancien plus lisible.)

Dans la WITHpartie, vous pouvez construire des lignes de n'importe quelle structure à la volée.

dezso
la source
Pour concaténer un non-jsonb avec jsonb :: SELECT row_to_json (r. *) FROM (SELECT c1, c2 :: jsonb FROM us_ca_monterey_aoc.test) as r
Andrew Scott Evans
9

Vous pouvez utiliser 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
la source