Как разобрать однострочный файл json, содержащий несколько объектов

Мне нужно прочитать некоторые данные JSON для обработки. У меня есть однострочный файл с несколькими объектами JSON, как я могу это проанализировать?

Я хочу, чтобы на выходе был файл с одной строкой на объект.

Я пробовал метод грубой силы, который будет рекурсивно использовать json.loads, чтобы проверить, действителен ли json, но я получаю разные результаты каждый раз, когда запускаю программу.

import json

with open('sample.json') as inp:
s = inp.read()

jsons = []

start, end = s.find('{'), s.find('}')
while True:
 try:
    jsons.append(json.loads(s[start:end + 1]))
    print(jsons)
except ValueError:
    end = end + 1 + s[end + 1:].find('}')
else:
    s = s[end + 1:]
    if not s:
        break
    start, end = s.find('{'), s.find('}')

for x  in jsons:
  writeToFilee(x)

Формат json можно увидеть здесь https://pastebin.com/DgbyjAG9

Вставьте образец вашего файла вместе с тем, как вы хотели бы получить вывод.

DirtyBit 09.04.2019 14:49

Вы хотите заменить taxi_group_id на что?

DirtyBit 09.04.2019 14:50

Я хочу разделить однострочный файл, содержащий несколько объектов, на многострочный файл, содержащий объект в каждой строке.

Jessica 09.04.2019 14:53

@Джессика, эти объекты как-то разделены? Или это просто как {...}{...}? Я нашел только 1 вхождение регулярного выражения "}\s*{" в предоставленной вами пасте, правильно ли я предполагаю, что этот файл содержит 2 разных объекта JSON, или их больше?

mr_m1m3 09.04.2019 15:00

как насчет jsons = s.replace('}{', '}|{').split('|') создать список строк json?

Chris Adams 09.04.2019 15:07

@AleksanderZień Они вообще не разделены, а всего 1200 объектов.

Jessica 09.04.2019 15:14

Каков результат, который вы ожидаете?

Kunal Mukherjee 09.04.2019 15:22

@Jessica Я подготовил черновой вариант решения, используя подход, описанный в комментарии Криса, но ответ, данный Сэмом Мейсоном, должен решить вашу проблему навсегда. :)

mr_m1m3 09.04.2019 15:25

Кстати, в примере данных есть объекты JSON верхнего уровня ровно 2. Это можно проверить вручную на сайте jsonlint.com. Нажмите «Проверить JSON». Он красиво печатает и останавливается на строке 1405. Это конец первого объекта JSON. Удалите все через этот "}". «Проверить JSON» еще раз — остальная часть файла является вторым объектом JSON.

ToolmakerSteve 16.10.2019 22:53
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
9
2 528
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

почему бы просто не использовать атрибут posJSONDecodeError, чтобы сказать вам, где разграничивать вещи?

что-то типа:

import json

def json_load_all(buf):
    while True:
        try:
            yield json.loads(buf)
        except json.JSONDecodeError as err:
            yield json.loads(buf[:err.pos])
            buf = buf[err.pos:]
        else:
            break

работает с вашими демонстрационными данными как:

with open('data.json') as fd:
    arr = list(json_load_all(fd.read()))

дает мне ровно два элемента, но я полагаю, у вас есть больше?

чтобы завершить это с помощью стандартной библиотеки, запись будет выглядеть примерно так:

with open('data.json') as inp, open('out.json', 'w') as out:
    for obj in json_load_all(inp.read()):
        json.dump(obj, out)
        print(file=out)

в противном случае пакет jsonlines хорош для работы с этим форматом данных

Следуя комментарию @Крис А, я подготовил этот фрагмент, который должен работать нормально:

with open('my_jsons.file') as file:
    json_string = file.read()

json_objects = re.sub('}\s*{', '}|!|{', json_string).split('|!|')
# replace |!| with whatever suits you best

for json_object in json_objects:
    print(json.loads(obj))

Однако этот пример станет бесполезным, как только строка '}{' появится в некотором значении внутри вашего JSON, поэтому я настоятельно рекомендую использовать решение @Сэм Мейсон.

Ответ принят как подходящий

Код ниже работал для меня:

import json
with open(input_file_path) as f_in: 
    file_data = f_in.read() 
    file_data = file_data.replace("}{", "},{") 
    file_data = "[" + file_data + "]"
    data = json.loads(file_data)

Другие вопросы по теме