其实里面最容易迷惑的,就是代码里的字符串与真实字符串的区别。在代码里需要用单引号或双引号将字符串包裹起来,这样一来就必须使用转义符,但是真实的字符串(例如你存入数据库的字符串)又是转义后的。上面看起来像是一段废话,但我认为确是主要矛盾。

考虑这样一个场景:你在数据库中用 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=(',', ':'))