我正在使用sqlite3表来存储python dicts(utf8内容),并使用JSON完成序列化。它在python2.7中工作正常但在3.3中失败。
架构:
CREATE TABLE mytable
(id INTEGER, book TEXT NOT NULL, d JSON NOT NULL, priority INTEGER NOT NULL DEFAULT(3),
PRIMARY KEY (id, book))
插入值时,dict将使用json.dumps(d)
序列化。
有缺陷的部分是检索以前保存的值。
import sys
import sqlite3
import json
filename = 'mydb.db'
sqlite3.register_converter('JSON', json.loads)
conn = sqlite3.connect(filename, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
c = conn.cursor()
c.execute('''SELECT book, id, d, priority FROM mytable''')
print(c.fetchall())
使用python2.7执行上述脚本时工作正常。但是,使用3.3会发生TypeError:
Traceback (most recent call last):
File "tests/py3error_debug.py", line 15, in <module>
c.execute('''SELECT book, id, d, priority FROM mytable''')
File "/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/lib/python3.3/json/__init__.py", line 319, in loads
return _default_decoder.decode(s)
File "/usr/local/Cellar/python3/3.3.2/Frameworks/Python.framework/Versions/3.3/lib/python3.3/json/decoder.py", line 352, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: can't use a string pattern on a bytes-like object
我无法发现2.7和3.3 JSON模块之间的本质区别(特别是关于json.loads
)并且我的想法已经不多了。
答案 0 :(得分:1)
根据Python 3 json module documentation:
json模块始终生成 str 对象,而不是字节对象。 ...
根据Python 3 sqlite3.register_converter documentation:
注册callable以将 bytestring 从数据库转换为自定义Python类型。 ...
如果你尝试加载bytesstring json,你会得到TypeError:
>>> json.loads('"0"')
'0'
>>> json.loads(b'"0"')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.3/json/__init__.py", line 319, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.3/json/decoder.py", line 352, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
TypeError: can't use a string pattern on a bytes-like object
您应该在使用bytes.decode调用json.loads
之前将字节转换为str。
sqlite3.register_converter('JSON', lambda x: json.loads(x.decode('utf-8')))