Вопрос-Ответ

Loading and parsing a JSON file with multiple JSON objects

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

Я пытаюсь загрузить и проанализировать файл 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"}
Переведено автоматически
Ответ 1

У вас есть текстовый файл формата 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

В случае, если вы используете pandas и вас заинтересует загрузка json файла в виде фрейма данных, вы можете использовать:

import pandas as pd
df = pd.read_json('file.json', lines=True)

А чтобы преобразовать его в массив json, вы можете использовать:

df.to_json('new_file.json')
Ответ 3

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

Ответ 4

Точно так же, как ответ Мартина Питерса, но, возможно, немного более питонистский, и, прежде всего, позволяющий передавать данные потоком (см. Вторую часть ответа):

import json

with open(filepath, "r") as f:
return list(map(json.loads, f))

map(function, iterable) Функция возвращает итератор, который применяется function к каждому элементу iterable, выдавая результаты (см. map() python doc).

И list преобразует этот итератор в ... список :)

Но вы можете представить себе, что вместо этого можно напрямую использовать итератор, возвращаемый map: он выполняет итерации по каждой из ваших строк json. Обратите внимание, что в этом случае вам нужно делать это в with open(filepath, "r") as f контексте: в этом сила этого подхода, строки json не полностью загружаются в список, они передаются потоком: функция map считывает каждую строку файла, когда next(iterator) вызывается for loop.

Это дало бы:

import json

with open(file path, "r") as f:
iterator_over_lines = map(json.loads, f)
# just as you would do with a list but here the file is streamed
for jsonline in iterator_over_lines:
# do something for each line
# the function mapped, json.loads is only call on each iteration
# that's why the file must stay opened

# You can try to call yourself the next function used by the for loop:
next_jsonline = next(iterator_over_lines)
nextnext_jsonline = next(iterator_over_lines)

И мне нечего добавить к ответу Martijn для объяснений о том, что такое jsonl (файл json построчно) и зачем его использовать!

python json file