web-dev-qa-db-fra.com

MySQL: renvoyer JSON à partir d'une requête SQL standard

J'ai lu sur les objets JSON et le type d'objet JSON. Je veux seulement faire une sélection et retourner JSON. Je ne veux pas nécessairement stocker un objet JSON. La sérialisation en soi n'est pas ma question. Les colonnes sont des colonnes Varchar, Int, etc. normales, pas d'objets JSON, des lignes de base de données "normales".

Puis-je faire un ancien SELECT régulier et retourner JSON pour MySQL?

N'est-ce pas ce que POUR JSON dans SQL SERVER et row_for_json fait dans PostgreSQL?

Ils semblaient en avance dans cette situation mais je ne voulais pas me tromper.

J'ai trouvé cette question à partir de 2016: https://stackoverflow.com/questions/35324795/mysql-5-7-return-row-as-json-using-new-json-features

10
johnny

A pris un peu de temps pour comprendre (plus habitué à PostgreSQL où les choses sont beaucoup plus faciles !), Mais si vous consultez l'amende manuel ici , sous 12.16.2 Functions That Create JSON Values, il y a la fonction JSON_ARRAY, mais ce n'est pas vraiment utile - du moins dans ce cas!

Pour répondre à la question "select and it return JSON", Il y a deux façons de procéder, toutes deux assez douloureuses!

Vous pouvez soit

  • utiliser un "hack" - voir le db-fiddle ici ,

  • ou utilisez ici l'une des nouvelles fonctions JSON fournies par MySQL - qui, ironiquement, semble être encore plus un hack que le hack lui-même! Uniquement avec MySQL! :-) (violon ici ).

Les deux réponses utilisent la fonction MySQL GROUP_CONCAT - ce message a aidé. Vous voudrez peut-être définir la variable système group_concat_max_len à un peu plus que sa valeur par défaut (un maigre 1024)!

La première requête est, comme vous pouvez l'imaginer, désordonnée (DDL et DML au bas de cette réponse):

SELECT CONCAT('[', better_result, ']') AS best_result FROM
(
SELECT GROUP_CONCAT('{', my_json, '}' SEPARATOR ',') AS better_result FROM
(
  SELECT 
    CONCAT
    (
      '"name_field":'   , '"', name_field   , '"', ',' 
      '"address_field":', '"', address_field, '"', ','
      '"contact_age":'  , contact_age
    ) AS my_json
  FROM contact
) AS more_json
) AS yet_more_json;

Résultat:

[{"name_field":"Mary","address_field":"address one","contact_age":25},{"name_field":"Fred","address_field":"address two","contact_age":35},{"name_field":"Bill","address_field":"address three","contact_age":47}]

ce qui est correct, mais, avouons-le, un peu un cauchemar!

Ensuite, il y a l'approche MySQL JSON_ARRAY() (qui est encore plus compliquée - merci MySQL pour votre implémentation (inexistante) de la fonction TRANSLATE()!).

SELECT
CONCAT
('[', REPLACE
  (
    REPLACE
    (
      GROUP_CONCAT
      (
        JSON_ARRAY
        (
          'name_field:', name_field, 
          'address_field:', address_field, 
          'age_field:', contact_age
        ) SEPARATOR ','
      ), '[', '{'
    ), ']', '}'
  ), ']'
) 
AS best_result2 
FROM contact

Même résultat!

====  TABLE CREATION and INSERT DDL and DML ============

    CREATE TABLE contact
    (
         name_field VARCHAR  (5) NOT NULL,
      address_field VARCHAR (20) NOT NULL,
      contact_age   INTEGER      NOT NULL
    );

    INSERT INTO contact
    VALUES
    ('Mary', 'address one',   25),
    ('Fred', 'address two',   35),
    ('Bill', 'address three', 47);
11
Vérace

Conversion d'une ligne en json

Cela ne me semble pas comme si vous vouliez agréger JSON. Vous dites que vous voulez l'équivalent de row_to_json, Si c'est le cas, je vous suggère de vérifier le plus simple JSON_OBJECT

SELECT JSON_OBJECT(
  'name_field', name_field,
  'address_field', address_field,
  'contact_age', contact_age
)
FROM contact;

Agrégation JSON

En remarque, si vous avez besoin d'agréger un jeu de résultats en json. alors le prochain MySQL 8 le fera pour vous.

  • JSON_ARRAYAGG() Retourne le jeu de résultats sous la forme d'un tableau JSON unique
  • JSON_OBJECTAGG() `Retourne le jeu de résultats comme un seul objet JSON
17
Evan Carroll

Pour un tableau d'objets JSON (un objet par ligne dans la requête), vous pouvez faire ceci:

SELECT JSON_ARRAYAGG(JSON_OBJECT("fieldA", fieldA, "fieldB", fieldB)) 
  FROM table;

Il en résulterait un seul tableau JSON contenant toutes les entrées:

[
  {
    "fieldA": "value",
    "fieldB": "value"
  },
  ...
]

Malheureusement, MySQL ne permet pas de sélectionner tous les champs avec *. Ce serait génial, mais ne fonctionne pas :

SELECT JSON_ARRAYAGG(JSON_OBJECT(*)) FROM table;
6
Eneko Alonso

Cela vous donnera la même réponse, mais un code beaucoup plus facile. Je viens d'utiliser json_object avec group_concat pour simplifier le autre réponse .

select 
    concat('[',
        GROUP_CONCAT(
            JSON_OBJECT(    
                'name_field', name_field
                ,'address_field', address_field
                ,'contact_age', contact_age
                )
            SEPARATOR ',')
    ,']')
    from contact;
3
dmelt