首页 > 解决方案 > 解析时髦的 JSON 时出现 JSONDecodeError

问题描述

最近,我开始使用 JSON(在 Debian 9 下使用 Python 3.7)。这是我有幸使用的第一个(可能是许多)JSON 数据集。

我使用 Python 内置的 JSON 模块来解释任意字符串和文件。我现在有一个大约 5570 行的数据库,其中包含有关给定服务器列表的信息。有很多事情正在筹备中,我已经制定了一个计划,但我被困在这个特殊的卫生设施上。

这是我用来解析的代码:

#!/usr/local/bin/python3.7
import json


def servers_from_json(file_name):
    with open(file_name, 'r') as f:
        data = json.loads(f.read())
        servers = [{'asn': item['data']['resource'], 'resource': item['data']['allocations'][0]['asn_name']} for item in data]
        return servers

servers = servers_from_json('working-things/working-format-for-parse')
print(servers) 

我的动机

我正在尝试将这些服务器中的每一个与它们的 ASN_NAME 匹配(这是一个直接从 RIPE 的 API 中提取的字段;从而为我提供与每个服务器所在的物理 dc 有关的信息。然后,一旦完成,我会将它们写入布尔值旁边的现有 SQL 表中。

所以,这就是它变得时髦的地方。如果我通过它运行整个数据集,我会收到以下错误消息

Traceback (most recent call last):
  File "./parse-test.py", line 12, in <module>
    servers = servers_from_json('2servers.json')
  File "./parse-test.py", line 7, in servers_from_json
    data = json.loads(f.read())
  File "/usr/local/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.7/json/decoder.py", line 340, in decode
    raise JSONDecodeError("Extra data", s, end)
json.decoder.JSONDecodeError: Extra data: line 38 column 2 (char 1098)

我注意到我的初始数据集的问题是每个 JSON 对象没有用 ,\n 分隔。做了一些清洁,仍然没有运气。

然后我将前 3 个(?)对象添加到一个完全干净的文件中,然后......成功。我可以让脚本以我想要的方式阅读和解释它们。

这是带有逗号分隔符的数据集:

http://db.farnworth.site/servers.json

这是工作数据集:

http://db.farnworth.site/working-format.json

有人有什么想法吗?

标签: pythonjsonparsing

解决方案


我在这里假设它|不会作为数据的一部分出现。并使用模块分离每个信息块|,然后将其转换为列表并加载每个列表项json。希望能帮助到你!

你可以试试:

import json
import re

with open("servers.json", 'r') as f:
    data = f.read()
    pattern = re.compile(r'\}\{')
    data = pattern.sub('}|{', data).split('|')
    for item in data:
        server_info = json.loads(item)
        allocations = server_info['data']['allocations']
        for alloc in allocations:
            print(alloc['asn_name'])


我可以读到output.json这样的

import json
import re

with open("output.json", 'r') as f:
    data = f.read()
    server_info = json.loads(data)  
    for item in server_info:
        allocations = item['data']['allocations']
        for alloc in allocations:
            print(alloc['asn_name'])

推荐阅读