【问题标题】:python 3 : deserialize nested dictionaries from sqlitepython 3:从sqlite反序列化嵌套字典
【发布时间】:2020-07-15 21:34:29
【问题描述】:

我有这个 sqlite3.register_converter 函数:

def str_to_dict(s: ByteString) -> Dict:
    if s and isinstance(s, ByteString):
        s = s.decode('UTF-8').replace("'", '"')
        return json.loads(s)
    raise TypeError(f'value : "{s}" should be a byte string')

返回此异常文本:

File "/usr/lib64/python3.7/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 30 (char 29)

遇到此字符串时:

s = b"{'foo': {'bar': [('for', 'grid')]}}"

似乎问题来自嵌套列表/元组/字典,但我不明白的是,在 sqlite shell 中,使用选择命令正确返回了值:

select * from table;

而从 python 脚本发出的相同命令返回了上述异常:

class SqliteDb:

    def __init__(self, file_path: str = '/tmp/database.db'):

        self.file_path = file_path
        self._db = sqlite3.connect(self.file_path, detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES)
        if self._db:
            self._cursor = self._db.cursor()
        else:
            raise ValueError

        # register data types converters and adapters
        sqlite3.register_adapter(Dict, dict_to_str)
        sqlite3.register_converter('Dict', str_to_dict)

        sqlite3.register_adapter(List, list_to_str)
        sqlite3.register_converter('List', str_to_list)

    def __del__(self):
        self._cursor.close()
        self._db.close()

    def select_from(self, table_name: str):
        with self._db:
            query = f'SELECT * FROM {table_name}'
            self._cursor.execute(query)

if __name__ == '__main__':

    try:
        sq = SqliteDb()
        selection_item = sq.select_from("table")[0]
        print(f'selection_item : {selection_item}')

    except KeyboardInterrupt:
        print('\n')
        sys.exit(0)

s,该值已经保存在数据库中,没有问题。只有选择会导致此问题。 那么,有人知道为什么吗?

【问题讨论】:

    标签: json python-3.x sqlite nested


    【解决方案1】:

    您的输入实际上是一个 Python dict 文字,并且包含诸如元组 ('for', 'grid') 之类的结构,即使您将单引号替换为双引号,也无法直接解析为 JSON。

    您可以改用ast.literal_eval 来解析输入:

    from ast import literal_eval
    
    def str_to_dict(s: ByteString) -> Dict:
        return literal_eval(s.decode())
    

    【讨论】:

    • 其实我很喜欢你的回答,但我仍然不知道为什么序列化在 shell 中工作而不是通过脚本。
    • 事实上,使用列表而不是元组解决了这个问题。但我仍然不知道为什么 sqlite shell 会起作用,但我了解了 ast :所以,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-02-19
    • 2011-09-18
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    • 2018-03-17
    • 2011-06-03
    相关资源
    最近更新 更多