其实里面最容易迷惑的,就是代码里的字符串与真实字符串的区别。在代码里需要用单引号或双引号将字符串包裹起来,这样一来就必须使用转义符,但是真实的字符串(例如你存入数据库的字符串)又是转义后的。上面看起来像是一段废话,但我认为确是主要矛盾。
考虑这样一个场景:你在数据库中用 text
类型存放 JSON 对象(JSON 对象默认都用双引号包裹字符串),你想要取出来做些修改再存进去。
假设数据库中存储的字符串是这样 {"id":1,"name": "le\"ee'e"}
(为了与数据库中的形式保持一致,我这里没用引号包裹整个字符串),并赋值给变量 target
然后首先 json.loads(target)
一下,会得到如下的 JSON 对象
{
"id": 1,
"name": "le\"ee'e"
}
给它随便做些修改,比如新增一个字段 extra
,然后 target
就变成这样
{
"id": 1,
"name": "le\"ee'e",
"extra": "something"
}
最后要把它存入数据库,一般直接用 cursor.execute()
,这个时候问题就来了,你会写出下面像这样的语句
cursor.execute("UPDATE table_name SET column_name = '%s' WHERE id = 1" % json.dumps(target))
或者你更习惯用单引号
cursor.execute('UPDATE table_name SET column_name = "%s" WHERE id = 1' % json.dumps(target))
上面的 sql 语句打印出来如下
UPDATE table_name SET column_name = '{"id": 1, "name": "le\"ee'e", "extra": "something"}' WHERE id = 1
UPDATE table_name SET column_name = "{"id": 1, "name": "le\"ee'e", "extra": "something"}" WHERE id = 1
可以看出,无论哪种都会导致 sql 报错,要想正确存入数据库,需要将对应符号都进行转义
cursor.execute("UPDATE table_name SET column_name = '%s' WHERE id = 1" % json.dumps(target).replace('\\', '\\\\').replace("'", "\\'"))
或者你更习惯用单引号
cursor.execute('UPDATE table_name SET column_name = "%s" WHERE id = 1' % json.dumps(target).replace('\\', '\\\\').replace('"', '\\"')
如果你不希望 JSON 字符串的逗号与冒号后有空格,需写成 json.dumps(target, separators=(',', ':'))