Updating json field in Postgres

前端 未结 3 1902
眼角桃花
眼角桃花 2021-02-20 05:53

Querying Postgres 9.3 by json field is really great. However i couldn\'t find a formal way to update the json object, for which i use an internal function written in plp

3条回答
  •  情书的邮戳
    2021-02-20 06:27

    No eval is required. Your issue is that you're not decoding the value as a json object.

    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)
    

    Not only that, but using eval to decode json is dangerous and unreliable. It's unreliable because json isn't Python, it just happens to evaluate a little bit like it much of the time. It's unsafe because you never know what you might be eval'ing. In this case you are largely protected by PostgreSQL's json parser:

    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__...
    

    ... but I won't be at all surprised if someone can slip an eval exploit past that. So the lesson here: don't use eval.

提交回复
热议问题