为啥 Python 不能解析这个 JSON 数据? [关闭]
Posted
技术标签:
【中文标题】为啥 Python 不能解析这个 JSON 数据? [关闭]【英文标题】:Why can't Python parse this JSON data? [closed]为什么 Python 不能解析这个 JSON 数据? [关闭] 【发布时间】:2011-02-19 14:29:19 【问题描述】:我在一个文件中有这个 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 这个问题是由于使用错误造成的,不是因为它可以被复制。 【参考方案1】:这里是修改后的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
【讨论】:
如果我们想添加一列来计算“地图”有多少观察值,我们该如何编写这个函数?【参考方案2】:您的数据无效JSON 格式。你有[]
,而你应该有:
[]
用于 JSON 数组,在 Python 中称为 list
用于 JSON 对象,在 Python 中称为 dict
这是您的 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"]
试试这些,看看它是否开始有意义。
【讨论】:
好的,所以我必须控制我的代码,因为这个 json 文件是从 java 对象生成的。谢谢。 感谢您的解决方案。我在打印时得到一个 unicode 符号。 (例如 u'valore' )。如何预防? 不错,但 python 在每个键之前添加了一个u'
。知道为什么吗?
这就是为什么你的文本类型是 unicode 而不是字符串。大多数情况下,最好为德语变音符号提供 unicode 文本,并与其他模块/程序等共享文本结果。所以你很好!
我想发表一个希望对您有所帮助的观察,但绝对是讽刺。我发现 pprint 模块不如用于漂亮打印 json 的 json 模块。如果你两个都试试,我想你会同意的。为了显示和调试我的 json 数据结构,我一直在做: output = json.dumps(data_structure, indent=2, sort_keys=True) print(output) 我想你会发现缩进控制、排序和智能dumps() 方法中的换行非常符合您的喜好。如果我的想法是错误的,请告诉我。【参考方案3】:
这个解析有两种类型。
-
从系统路径的文件中解析数据
从远程 URL 解析 JSON。
从文件中,您可以使用以下内容
import json
json = json.loads(open('/path/to/file.json').read())
value = json['key']
print(json['value'])
这篇文章解释了使用两种场景的完整解析和获取值。Parsing JSON using Python
【讨论】:
非常感谢“从系统上的文件中解析数据”方法!【参考方案4】:Justin Peel's answer 确实很有帮助,但如果您使用 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 数据加载到内存中是一个问题。 我在 JS、Java、Kotlin、cpp、rust 几乎所有我使用的语言中都看到了这一点。 把内存问题当作一个笑话对我来说:)
另一方面,我不认为你可以不阅读所有内容就解析 json。
【讨论】:
为什么在 Python 3 中应避免使用json.load
以支持 .loads
?
您链接的页面没有说明要避免load
。
这个答案在不需要时将整个文件读取到内存中,并建议在 Python 3 中不能延迟读取 JSON 文件,这是不正确的。很抱歉,很明显反对票。
这个答案不准确。没有理由不在 python3 中将 json.load 与打开文件处理程序一起使用。很抱歉投了反对票,但您似乎没有仔细阅读上述 cmets。
+1 这个答案太棒了!谢谢你,让我远离寻找可以使用字符串的函数,因为我只处理不是文件的字符串和网络请求!【参考方案5】:
如果您使用的是 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
【讨论】:
这会使文件句柄保持打开状态。使用with
语句会更好【参考方案6】:
作为 python3 用户,
load
和 loads
方法之间的区别很重要,尤其是当您从文件中读取 json 数据时。
如文档中所述:
json.load:
反序列化 fp(支持 .read() 的文本文件或二进制文件 包含 JSON 文档的文件)到 Python 对象使用这个 换算表。
json.loads:
json.loads:反序列化 s(一个 str、bytes 或 bytearray 实例 包含 JSON 文档)到使用此转换的 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 文件。【参考方案7】:“Ultra JSON”或简单的“ujson”可以处理在您的 JSON 文件输入中包含 []
。如果您将 JSON 输入文件作为 JSON 元素列表读入程序;例如,[[], , [], etc...]
ujson 可以处理任意顺序的字典列表、列表字典。
您可以在Python package index 中找到ujson,API 几乎与Python 内置的json
库相同。
如果您要加载较大的 JSON 文件,ujson 也会快得多。您可以在提供的同一链接中查看与其他 Python JSON 库相比的性能详细信息。
【讨论】:
【参考方案8】:您的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 Justin Peel's answer,此答案基于此。
您现在还可以像这样访问单个值:
data["maps"][0]["id"] # will return 'blabla'
data["masks"]["id"] # will return 'valore'
data["om_points"] # will return 'value'
【讨论】:
我对此投了反对票。也许不清楚,为什么我认为需要另一个答案。添加了关于 with 语句兼容性的说明。 抱歉回滚,但建议的代码会使data_file
open
ed 的时间过长。
参考 2.6 文档 (docs.python.org/2.6/library/io.html),在 "with" 上下文中打开文件会自动关闭文件。
@SteveS。是的,但不是在离开上下文之前。 pprint
ing 在with
-context 中保持data_file
的打开时间更长。
@GayanPathirage 你可以像data["om_points"]
,data["masks"]["id"]
一样访问它。这个想法是您可以通过指定“关键路径”来达到字典中的任何级别。如果您收到 KeyError
异常,则表示路径中不存在密钥。注意拼写错误或检查字典的结构。【参考方案9】:
data = []
with codecs.open('d:\output.txt','rU','utf-8') as f:
for line in f:
data.append(json.loads(line))
【讨论】:
如果文件中有多个 json 对象,这是正确的解决方案。json.loads
不解码多个 json 对象。否则,您会收到“额外数据”错误。
这是最好的答案。否则,它会给出“额外数据”错误。
文件中有多个 json 对象意味着文件本身实际上不是有效的 json。如果你有多个对象要包含在一个 json 文件中,它们应该包含在文件顶层的一个数组中。
一个文件中有多个 json 对象意味着该文件不是单个 json 对象。这很明显。从对象中创建一个数组是一个明显的解决方法。但是 JSON 在设计上是明确终止的,几乎在每个级别(
、]
或 "
)。因此,您确实可以在单个字符串或单个文件中连接多个对象,而不会产生歧义。这里的问题是,当传递多个对象时,期望单个对象的解析器会失败。
在单个文件中存储多个 JSON 对象的广告:有一个“标准” - jsonlines.org/examples 在.jsonl
(json 行)中,对象由换行符分隔,这使得用于解析琐碎的预处理,并允许轻松拆分/批处理文件,而无需担心开始/结束标记。以上是关于为啥 Python 不能解析这个 JSON 数据? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Javascript 不能从字符串文字中解析这个 JSON 数组?
为啥 Javascript 不能从字符串文字中解析这个 JSON 数组?