为啥 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 用户

loadloads 方法之间的区别很重要,尤其是当您从文件中读取 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 opened 的时间过长。 参考 2.6 文档 (docs.python.org/2.6/library/io.html),在 "with" 上下文中打开文件会自动关闭文件。 @SteveS。是的,但不是在离开上下文之前。 pprinting 在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 数组?

为啥不能从文件中解析 JSON?

python中为啥用json有啥作用

为啥 jQuery dataTables 不能解析我的 JSON?

为啥我不能在 Python 中反序列化带有单引号的 JSON 字符串?