简体   繁体   English

Python dict反序列化在python2.7中有效,在3.3中失败

[英]Python dict deserialization works in python2.7, fails in 3.3

I'm using a sqlite3 table to store python dicts (utf8 content) and serialization is done with JSON. 我正在使用sqlite3表存储python dict(utf8内容),并且使用JSON完成了序列化。 It works fine in python2.7 but fails in 3.3. 它在python2.7中工作正常,但在3.3中失败。

Schema: 架构:

CREATE TABLE mytable
  (id INTEGER, book TEXT NOT NULL, d JSON NOT NULL, priority INTEGER NOT NULL DEFAULT(3), 
   PRIMARY KEY (id, book))

When inserting values, the dict is serialized with json.dumps(d) . 插入值时,字典将使用json.dumps(d)序列化。 The faulty part is retrieving the previously saved values. 故障部分正在检索先前保存的值。

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())

The above script works fine when executed with python2.7. 上面的脚本与python2.7一起执行时效果很好。 However, using 3.3 a TypeError occures: 但是,使用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

I can't spot an essential difference between the 2.7 and 3.3 JSON modules (especially regarding json.loads ) and I'm running out of ideas. 我无法发现2.7和3.3 JSON模块之间的本质区别(尤其是关于json.loads ),而且我的想法已经用完了。

According to Python 3 json module documentation : 根据Python 3 json模块文档

The json module always produces str objects, not bytes objects. json模块总是产生str对象,而不是byte对象。 ... ...

According to Python 3 sqlite3.register_converter documentation : 根据Python 3 sqlite3.register_converter文档

Registers a callable to convert a bytestring from the database into a custom Python type. 注册一个callable,以将字节串从数据库转换为自定义Python类型。 ... ...

If you try to load bytesstring json, you get TypeError: 如果尝试加载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

You should convert bytes to str before call json.loads using bytes.decode . 在使用bytes.decode调用json.loads之前,应将字节转换为str。

sqlite3.register_converter('JSON', lambda x: json.loads(x.decode('utf-8')))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM