17/09/2023

0. JSON

Lu 456 fois Licence Creative Commons

Manipulations de JSON

Une des forces de PostgreSQL est sa capacité à traiter des documents JSON grâce à de nombreux opérateurs et fonctions.
Il n'est généralement pas recommandé de stocker du JSON dans une base de données relationnelle car cela va à l'encontre des principes de normalisation, mais on peut cependant se retrouver face à des situations où nous sommes contraints de traiter du JSON en SQL.

Par exemple le framework Symfony propose par défaut de stocker les "rôles" des utilisateurs (pour les droits d'accès) sous forme de tableau JSON, dans une colonne. Pour chercher les utilisateurs par rôle, on se retrouve limité par les capacités de l'ORM qui ne fournit pas nativement ce genre de manipulation.
Avec l'opérateur ? on peut savoir si une valeur existe dans un objet ou tableau JSON. Ici en testant si ROLE_ADMIN est présent dans des tableaux:

-- true
SELECT '["ROLE_ADMIN", "ROLE_EDITOR"]' ? 'ROLE_ADMIN';
-- false
SELECT '["ROLE_EDITOR"]' ? 'ROLE_ADMIN';

En dehors d'opérations de test, la lecture dans des documents JSON complexes est également possible.
Ici en utilisant l'opérateur #> sur une chaîne transformée en type JSONB à laquelle on passe chaque clé pour rechercher une information:

SELECT '{"id": 42, "details": {"locations": ["Paris", "London"]}}'::jsonb #> '{details, locations, 1}'
?column?
"London"

Ou avec une fonction à laquelle on passe le JSON ainsi qu'une expression jsonpath pour obtenir tous les noms de fichiers d'une stack trace:

SELECT jsonb_path_query(
    '{
        "exception": {
            "time": "2022-09-16 09:15:03",
            "message": "Error: something bad happened.",
            "stack_trace": [
                {
                    "file": "vendor/author/package/src/Business/Service.php",
                    "line": 42
                },
                {
                    "file": "src/Service/Something.php",
                    "line": 42
                },
                {
                    "file": "src/Controller/Homepage.php",
                    "line": 42
                }
            ]
        }
    }',
    '$.exception.stack_trace[*].file'
)
jsonb_path_query
"vendor/author/package/src/Business/Service.php"
"src/Service/Something.php"
"src/Controller/Homepage.php"

Il y a de nombreuses possibilités de manipulation de JSON avec PostgreSQL, ce qui peut rapidement demander de lire la documentation en fonction du besoin.