我有一个具有以下结构的 .json:
[
{
"Country": "Spain",
"Age": "14"
},
{
"Country": "China",
"Age": "16"
},
]
我尝试使用以下方法阅读它:
import json
from pprint import pprint
with open('json.json') as f:
data = json.load(f)
pprint(data)
但它抛出了以下错误:
ValueError:无法解码任何 JSON 对象
JSON 由 Octoparse 软件返回给我,所以我认为它没有格式错误。
如何将值存储在我的脚本本地的 json 中?
我希望它具有以下格式:
{"14":"Spain","16":"China"}
谢谢。
诊断
虽然粘贴到问题中的 JSON 是正确的(除了留下额外的尾随逗号的复制错误),但当用户在自己的 JSON 上尝试相同的操作时,他们会得到错误
ValueError
,这不是很丰富的信息。在与用户进行一些对话后,我得到了他真正使用的 json 文件,我尝试使用 Python2(这是用户使用的版本)复制他的代码的执行,尽管提供的 JSON看起来正确,我得到错误:
相反,如果我使用 Python3 重复执行,则诊断会更加准确,并证实我怀疑文件开头存在导致问题的隐藏字符:
问题
该文件最初包含一系列称为“BOM”(字节顺序标记)的字节,这些字节在屏幕上显示或在编辑器中加载时不可见,但从程序中读取时则不可见。
如果文件是 UTF-16 格式,这些字节的目的是允许读取它的程序推断生成文件的体系结构的字节序(即,它是little endian还是big endian)。但是,在 UTF-8 文件中插入这些字节是没有意义的,因为 UTF-8 格式不受字节顺序问题的影响。
然而,许多编辑器和 Windows 程序在保存为 UTF-8 时仍然会插入这些字节,这显然与 JSON 标准不兼容。
解决方案
使用 python3 可以传递
open()
一个参数,该参数指定要读取的文件的编码(如果未传递,则假设utf-8
)。在这种情况下,它必须被utf-8-sig
传递,因为 Python3 本身在其错误消息中告诉我们。但是,由于用户使用的是Python2,所以在打开文件的时候并没有可能传递那个参数,所以我们只能把整个文件读成一个字节串,然后将该字符串编码成Unicode,使用有问题的格式。稍后我们将使用
json.loads()
instead ofjson.load()
,因为这样我们可以传递正确解码的 unicode 字符串而不是文件。即:
这个解决方案比Python3占用更多的内存,因为我们必须在解析json之前加载整个文件,而在python3中它会在读取时解析,但是由于文件不是很大(61K)没有问题。