【问题标题】:Some readble content, but impossible to JSON dump to file一些可读的内容,但不可能 JSON 转储到文件
【发布时间】:2015-04-03 10:54:09
【问题描述】:

这个text file(仅30字节,内容为'(Ne pas r\xe9pondre a ce message)')可以打开并成功插入dict

import json

d = {}

with open('temp.txt', 'r') as f:
   d['blah'] = f.read()

with open('test.txt', 'w') as f:
    data = json.dumps(d)
    f.write(data)    

但是不可能将dict 转储到 JSON 文件中(参见下面的回溯)。为什么?

我尝试了各种 SO 问题提供的许多解决方案。我能得到的最接近的解决方案是this answer。使用它时,我可以转储到文件,但是 JSON 文件看起来像这样:

# test.txt
{"blah": "(Ne pas r\u00e9pondre a ce message)"}

而不是

# test.txt
{"blah": "(Ne pas répondre a ce message)"}

追溯:

  File "C:\Python27\lib\json\encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe9 in position 9: invalid continuation byte
[Finished in 0.1s with exit code 1]

【问题讨论】:

    标签: python json unicode utf-8


    【解决方案1】:

    您的文件不是 UTF-8 编码的。它使用 Latin 编解码器,例如 ISO-8859-1 或 Windows Codepage 1252。读取文件会为您提供编码文本。

    JSON 然而需要 Unicode 文本。 Python 2 有一个单独的 Unicode 类型,字节字符串(str 类型)需要使用合适的编解码器进行解码。 json.dumps() 函数默认使用 UTF-8; UTF-8 是一种广泛使用的编解码器,用于编码 Unicode 文本数据,可以处理标准中的所有代码点,也是 JSON 字符串使用的默认编解码器(JSON 要求文档以3 个 UTF 编解码器)。

    您需要手动解码字符串或告诉json.dumps() 字节字符串使用什么编解码器:

    data = json.dumps(d, encoding='latin1')  # applies to all bytestrings in d
    

    d['blah'] = d['blah'].decode('latin1')
    data = json.dumps(d)
    

    或在阅读时使用io.open() 进行解码:

    import io
    
    with io.open('test.txt', 'w', encoding='latin1') as f:
        d['blah'] = f.read()
    

    默认情况下,json 库使用 JSON 标准允许的 \uhhhh 转义语法生成 ASCII 安全的 JSON 输出。 这完全正常,输出是有效的 JSON,任何兼容的 JSON 解码器都可以读取。

    如果您必须生成不带\uhhhh 转义序列的UTF-8 编码输出,请参阅Saving utf-8 texts in json.dumps as UTF8, not as \u escape sequence

    【讨论】:

    • 谢谢,但是使用它时,输出文件如下所示:{"blah": "(Ne pas r\u00e9pondre a ce message)"}
    • @Basj:是的,因为那是数据的正确 JSON 编码。如果您想将代码点编码为 UTF-8 而不是使用转义序列,请参阅Saving utf-8 texts in json.dumps as UTF8, not as \u escape sequence
    • Arghh,这很烦人......我想使用 JSON 来拥有两者 1)可以轻松加载到 python 中的 dict 2)在文本编辑器中人类可读的东西......全部\u00*,它在文本编辑器中将不再是人类可读的。我将无法使用标准搜索工具“搜索”诸如“répondre”之类的模式。
    • 我已经尝试过您在过去 2 小时内提供的最后一个链接 stackoverflow.com/questions/18337407/… ;) 但没有成功。它在这里如何工作?
    • @Basj: json.dumps(d, encoding='latin1', ensure_ascii=False).encode('utf8') 产生 UTF-8 输出。
    猜你喜欢
    • 2016-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多