PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Mise à jour du champ json dans Postgres

Pas d'eval est requis. Votre problème est que vous ne décodez pas la valeur en tant qu'objet json.

CREATE OR REPLACE FUNCTION json_update(data json, key text, value json)
RETURNS json AS
$BODY$
   from json import loads, dumps
   if key is None: return data
   js = loads(data)
   # you must decode 'value' with loads too:
   js[key] = loads(value)
   return dumps(js)
$BODY$
LANGUAGE plpythonu VOLATILE;

postgres=# SELECT json_update('{"a":1}', 'a', '{"innerkey":"innervalue"}');
            json_update            
-----------------------------------
 {"a": {"innerkey": "innervalue"}}
(1 row)

Non seulement cela, mais en utilisant eval pour décoder json est dangereux et peu fiable. Ce n'est pas fiable car json n'est pas Python, il arrive juste qu'il s'évalue un peu comme ça la plupart du temps. C'est dangereux parce que vous ne savez jamais ce que vous pourriez évaluer. Dans ce cas, vous êtes largement protégé par l'analyseur json de PostgreSQL :

postgres=# SELECT json_update(
postgres(#    '{"a":1}', 
postgres(#    'a', 
postgres(#    '__import__(''shutil'').rmtree(''/glad_this_is_not_just_root'')'
postgres(# );
ERROR:  invalid input syntax for type json
LINE 4:          '__import__(''shutil'').rmtree(''/glad_this_is_not_...
                 ^
DETAIL:  Token "__import__" is invalid.
CONTEXT:  JSON data, line 1: __import__...

... mais je ne serais pas du tout surpris si quelqu'un pouvait glisser un eval exploiter au-delà. Donc la leçon ici :n'utilisez pas eval .