Загрузка и анализ файла JSON с несколькими объектами JSON

101

Я пытаюсь загрузить и проанализировать файл JSON в Python . Но я застрял, пытаясь загрузить файл:

import json
json_data = open('file')
data = json.load(json_data)

Урожайность:

ValueError: Extra data: line 2 column 1 - line 225116 column 1 (char 232 - 160128774)

Посмотрел на 18.2. json- Кодировщик и декодер JSON в документации Python, но читать эту ужасно выглядящую документацию довольно обескураживает.

Первые несколько строк (анонимные со случайными записями):

{"votes": {"funny": 2, "useful": 5, "cool": 1}, "user_id": "harveydennis", "name": "Jasmine Graham", "url": "http://example.org/user_details?userid=harveydennis", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 2, "cool": 4}, "user_id": "njohnson", "name": "Zachary Ballard", "url": "https://www.example.com/user_details?userid=njohnson", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 0, "cool": 4}, "user_id": "david06", "name": "Jonathan George", "url": "https://example.com/user_details?userid=david06", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 6, "useful": 5, "cool": 0}, "user_id": "santiagoerika", "name": "Amanda Taylor", "url": "https://www.example.com/user_details?userid=santiagoerika", "average_stars": 3.5, "review_count": 12, "type": "user"}
{"votes": {"funny": 1, "useful": 8, "cool": 2}, "user_id": "rodriguezdennis", "name": "Jennifer Roach", "url": "http://www.example.com/user_details?userid=rodriguezdennis", "average_stars": 3.5, "review_count": 12, "type": "user"}
Число Пи_
источник

Ответы:

223

У вас есть текстовый файл в формате JSON Lines . Вам нужно проанализировать ваш файл построчно:

import json

data = []
with open('file') as f:
    for line in f:
        data.append(json.loads(line))

Каждая строка содержит допустимый JSON, но в целом это недопустимое значение JSON, так как отсутствует список верхнего уровня или определение объекта.

Обратите внимание, что, поскольку файл содержит JSON на строку, вам не нужно будет пытаться разобрать его все за один раз или найти потоковый парсер JSON. Теперь вы можете выбрать обработку каждой строки отдельно перед переходом к следующей, экономя память в процессе. Вероятно, вы не захотите добавлять каждый результат в один список, а затем обрабатывать все, если ваш файл действительно большой.

Если у вас есть файл, содержащий отдельные объекты JSON с разделителями между ними, используйте Как использовать модуль json для чтения одного объекта JSON за раз? для анализа отдельных объектов с использованием буферизованного метода.

Мартейн Питерс
источник
2
+1 Может быть, стоит отметить, что если вам не нужны сразу все объекты, то обработка их по одному может оказаться более эффективным подходом. Таким образом, вам не нужно будет хранить данные в памяти целиком, а хранить их в отдельности.
Tadeck
1
@Pi_: у вас будет словарь, поэтому просто обращайтесь к полям как к ключам:data = json.loads(line); print data[u'votes']
Martijn Pieters
1
@Pi_: затем распечатайте результат json.loads () или используйте отладчик для проверки.
Мартейн Питерс
1
@Pi_: нет; не путайте формат JSON с представлением Python dict. Вы видите словари Python со строками.
Мартин Питерс
1
@ user2441441: см. связанный ответ из сообщения здесь.
Мартейн Питерс
11

для тех, кто наткнулся на этот вопрос: jsonlinesбиблиотека python (намного моложе этого вопроса) элегантно обрабатывает файлы с одним документом json на строку. см. https://jsonlines.readthedocs.io/

Wouter Bolsterlee
источник
4

То есть плохо отформатирован. У вас есть один объект JSON на строку, но они не содержатся в более крупной структуре данных (т.е. массиве). Вам нужно будет либо переформатировать его так, чтобы он начинался [и заканчивался ]запятой в конце каждой строки, либо анализировать его построчно как отдельные словари.

Дэниел Розман
источник
20
С файлом размером 50 МБ OP, вероятно, в любом случае лучше будет обрабатывать данные построчно. :-)
Martijn Pieters
11
Отформатирован ли файл плохо, зависит от точки зрения. Если он был задуман в формате «строки JSON», он действителен. См .: jsonlines.org
LS