为什么Python无法解析此JSON数据?


1438

我在文件中有此JSON:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [
        "id": "valore"
    ],
    "om_points": "value",
    "parameters": [
        "id": "valore"
    ]
}

我编写了以下脚本来打印所有JSON数据:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

但是,该程序会引发异常:

Traceback (most recent call last):
  File "<pyshell#1>", line 5, in <module>
    data = json.load(f)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 355, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 13 column 13 (char 213)

如何解析JSON并提取其值?


@kederrac给出的原因:“此问题是由错字或无法重现的问题引起的。” json无效。
罗布

@kederrac此问题是由使用错误引起的,不是因为可以复制它。
罗布

Answers:


2126

您的数据不是有效的JSON格式。您有[]什么时候应该拥有{}

  • []用于JSON数组,list在Python 中称为
  • {}用于JSON对象(dict在Python 中称为JSON对象)

JSON文件的外观如下:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": {
        "id": "valore"
    },
    "om_points": "value",
    "parameters": {
        "id": "valore"
    }
}

然后,您可以使用您的代码:

import json
from pprint import pprint

with open('data.json') as f:
    data = json.load(f)

pprint(data)

使用数据,您现在还可以找到类似的值:

data["maps"][0]["id"]
data["masks"]["id"]
data["om_points"]

试试看,看看是否有意义。


1
好的,所以我必须控制我的代码,因为此json文件是从java对象生成的。谢谢。
米歇尔

5
感谢您的解决方案。我在打印时得到一个unicode符号。(例如u'valore')。怎么预防呢?
diaryfolio 2015年

6
不错,但是python u'在每个键之前添加了一个。知道为什么吗?
CodyBugstein 2015年

7
这就是为什么您的文本是unicode类型而不是string类型的原因。在大多数情况下,最好以unicode编码文本以表达德国变音符号,并与其他模块/程序等共享文本结果。所以你很好!
Michael P

2
我想提出一个希望对大家有帮助的观察结果,而且肯定具有讽刺意味。我发现pprint模块不如json模块漂亮打印json。如果您同时尝试它们,我想您会同意的。为了显示和调试我的json数据结构,我一直在做:output = json.dumps(data_structure,indent = 2,sort_keys = True)print(output)我想您会发现indent-control,sorting和smart在dumps()方法中进行换行非常符合您的喜好。如果我的想法是错误的,请让我知道。
拉罗德(Larold)'18 -10-12

307

data.json应该看起来像这样:

{
 "maps":[
         {"id":"blabla","iscategorical":"0"},
         {"id":"blabla","iscategorical":"0"}
        ],
"masks":
         {"id":"valore"},
"om_points":"value",
"parameters":
         {"id":"valore"}
}

您的代码应为:

import json
from pprint import pprint

with open('data.json') as data_file:    
    data = json.load(data_file)
pprint(data)

请注意,这仅在Python 2.6及更高版本中有效,因为它取决于with-statement。在Python 2.5中使用from __future__ import with_statement,在Python <= 2.4中,请参见Justin Peel的答案,该答案基于该答案。

您现在还可以像这样访问单个值:

data["maps"][0]["id"]  # will return 'blabla'
data["masks"]["id"]    # will return 'valore'
data["om_points"]      # will return 'value'

7
我对此表示不满。也许还不清楚,为什么我认为还需要另一个答案。添加了有关with语句兼容性的注释。
Bengt

很抱歉回滚,但是建议的代码将使data_file opened 保存的时间比必要的时间长。
Bengt

参考2.6文档(docs.python.org/2.6/library/io.html),在“ with”上下文中打开文件将自动关闭该文件。
Steve S.

1
@SteveS。是的,但在离开上下文之前不会。-context pprint中的withing使data_file打开时间更长。
Bengt 2015年

1
@GayanPathirage你访问它像data["om_points"]data["masks"]["id"]。这个想法是,您可以通过指定“关键路径”来达到字典中的任何级别。如果收到KeyError异常,则表示该路径中不存在该密钥。注意拼写错误或检查字典的结构。
纳曼

71

贾斯汀·皮尔(Justin Peel)的回答确实很有帮助,但是,如果您使用的是Python 3,则应按以下方式读取JSON:

with open('data.json', encoding='utf-8') as data_file:
    data = json.loads(data_file.read())

注意:使用json.loads代替json.load。在Python 3中,json.loads采用字符串参数。json.load采用类似文件的对象参数。data_file.read()返回一个字符串对象。

老实说,在大多数情况下,将所有json数据加载到内存中都不是问题。


10
为什么要json.load避免.loads使用Python 3?
Zearin

10
您链接的页面没有说明如何避免load
Dan Hulme

28
这个答案不必将整个文件读取到内存中,并且建议在Python 3中不能延迟读取JSON文件,这是不正确的。抱歉,很显然是反对票。
卢卡斯Rogalski

10
这个答案不正确。没有理由不将json.load与python3中的打开文件处理程序一起使用。不好意思,但是您似乎没有很仔细地阅读以上评论。
dusktreader

5
+1这个答案很棒!谢谢您的帮助,让我不去寻找可使用字符串的函数,因为我只处理非文件的字符串和网络请求!
newpeople

54
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
    for line in f:
       data.append(json.loads(line))

8
如果文件中有多个json对象,则这是正确的解决方案。json.loads不解码多个json对象。否则,您会收到“额外数据”错误。
yasin_alm

这是最好的答案。否则,将显示“额外数据”错误。
Earthx9 2013年

39
在文件中具有多个json对象意味着文件本身实际上不是有效的json。如果您要在json文件中包含多个对象,则应将它们包含在文件顶层的数组中。
dusktreader

一个文件中有多个json对象意味着该文件不是单个json对象。这很明显。用对象制作单个数组是一个明显的解决方法。但是JSON是由设计明确的终止,几乎所有层面(通过}]")。因此,您确实可以将多个对象串联在单个字符串或单个文件中,而不会产生歧义。这里的问题是,当一个解析器传递了多个对象时,它预期单个对象会失败。
MSalters,

广告将多个JSON对象存储在一个文件中:这是一个“标准” -jsonlines.org/examples.jsonl(在json行中),对象之间用换行符分隔,这使得对语法的预处理变得微不足道,并且允许轻松拆分/批处理文件而无需担心开始/结束标记。
塞比

13

“超JSON”或简称“ ujson”可以处理[]您的JSON文件输入中的内容。如果您正在将程序中的JSON输入文件作为JSON元素列表读取;例如,[{[{}]}, {}, [], etc...]ujson可以处理字典列表的任何任意顺序,即列表字典。

您可以在Python包索引中找到ujson,并且该API与Python的内置json库几乎相同。

如果您要加载较大的JSON文件,则ujson也会更快。与提供的相同链接中的其他Python JSON库相比,您可以看到性能详细信息。


9

如果您使用的是Python3,则可以尝试将(connection.json文件)JSON 更改为:

{
  "connection1": {
    "DSN": "con1",
    "UID": "abc",
    "PWD": "1234",
    "connection_string_python":"test1"
  }
  ,
  "connection2": {
    "DSN": "con2",
    "UID": "def",
    "PWD": "1234"
  }
}

然后使用以下代码:

connection_file = open('connection.json', 'r')
conn_string = json.load(connection_file)
conn_string['connection1']['connection_string_python'])
connection_file.close()
>>> test1

1
这也适用于2.7.5
siddardha

17
这使文件句柄保持打开状态。使用with声明会更好
Corey Goldberg

6

在这里,您可以使用修改后的data.json文件:

{
    "maps": [
        {
            "id": "blabla",
            "iscategorical": "0"
        },
        {
            "id": "blabla",
            "iscategorical": "0"
        }
    ],
    "masks": [{
        "id": "valore"
    }],
    "om_points": "value",
    "parameters": [{
        "id": "valore"
    }]
}

您可以使用以下几行在控制台上调用或打印数据:

import json
from pprint import pprint
with open('data.json') as data_file:
    data_item = json.load(data_file)
pprint(data_item)

预期输出print(data_item['parameters'][0]['id'])

{'maps': [{'id': 'blabla', 'iscategorical': '0'},
          {'id': 'blabla', 'iscategorical': '0'}],
 'masks': [{'id': 'valore'}],
 'om_points': 'value',
 'parameters': [{'id': 'valore'}]}

预期输出print(data_item['parameters'][0]['id'])

valore

如果我们想添加一列来统计“地图”有多少个观测值,我们该如何编写此函数?
晨曦

5

该解析有两种类型。

  1. 从系统路径解析文件中的数据
  2. 从远程URL解析JSON。

从文件中,您可以使用以下内容

import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print json['value']

该小节解释了使用两种情况的完整解析和获取值。使用Python解析JSON


4

作为python3用户

loadloads方法之间的区别非常重要,尤其是当您从文件中读取json数据时。

如文档中所述:

json.load:

使用此转换表将fp(支持.read()的文本文件或包含JSON文档的二进制文件)反序列化为Python对象。

json.loads:

json.loads:使用此转换表将s(包含JSON文档的str,字节或字节数组实例)反序列化为Python对象。

json.load方法可以读取二进制文件,因此可以直接读取打开的json文档。

with open('./recipes.json') as data:
  all_recipes = json.load(data)

结果,您的json数据以根据此转换表指定的格式可用:

https://docs.python.org/3.7/library/json.html#json-to-py-table


这是对问题的答案如何?用户正在使用正确的方法加载json文件。
Raj006
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.