更新Postgres中的json字段

 tql 发布于 2023-02-03 08:41

通过json字段查询Postgres 9.3非常棒.但是我找不到更新json对象的正式方法,为此我使用plpythonu编写的内部函数基于之前的帖子(如何修改新的PostgreSQL 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)
   js[key] = value
   return dumps(js)
$BODY$
LANGUAGE plpythonu VOLATILE

当我的json更新保持扁平和简单时,它的效果非常好.假设"聊天"是在"GO_SESSION"表中提交的json类型,并包含{"a":"1","b":"2"},以下代码将更改"b"值并将"chat"更改为是{"a":"1","b":"5"}

update "GO_SESSION" set chat=json_update(chat,'b','5') where id=3

问题是当我试图给'b'另一个对象而不是一个简单的值时:

update "GO_SESSION" set chat=json_update(chat,'b','{"name":"steve"}') where id=3

数据库中的结果是'b'包含转义字符串而不是真正的json对象:

{"a":"1","b":"{\"name \":\"steve \"}"}

我已经尝试了不同的方法来unescape或转储我的json以保持'b'为对象,但找不到解决方案.

谢谢

1 个回答
  • 不需要eval.您的问题是您没有将值解码为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)
    

    不仅如此,使用eval解码json是危险和不可靠的.这是不可靠的,因为json不是Python,它恰好在很多时候都有点像它.这是不安全的,因为你永远不知道你的评价是什么.在这种情况下,你很大程度上受PostgreSQL的json解析器保护:

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

    ......但是如果有人能够eval利用这个漏洞,我将不会感到惊讶.所以这里的教训是:不要使用eval.

    2023-02-03 08:46 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有