Мне нужно прочитать некоторые данные 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
Вы хотите заменить taxi_group_id
на что?
Я хочу разделить однострочный файл, содержащий несколько объектов, на многострочный файл, содержащий объект в каждой строке.
@Джессика, эти объекты как-то разделены? Или это просто как {...}{...}? Я нашел только 1 вхождение регулярного выражения "}\s*{" в предоставленной вами пасте, правильно ли я предполагаю, что этот файл содержит 2 разных объекта JSON, или их больше?
как насчет jsons = s.replace('}{', '}|{').split('|')
создать список строк json?
@AleksanderZień Они вообще не разделены, а всего 1200 объектов.
Каков результат, который вы ожидаете?
@Jessica Я подготовил черновой вариант решения, используя подход, описанный в комментарии Криса, но ответ, данный Сэмом Мейсоном, должен решить вашу проблему навсегда. :)
Кстати, в примере данных есть объекты JSON верхнего уровня ровно 2. Это можно проверить вручную на сайте jsonlint.com. Нажмите «Проверить JSON». Он красиво печатает и останавливается на строке 1405. Это конец первого объекта JSON. Удалите все через этот "}". «Проверить JSON» еще раз — остальная часть файла является вторым объектом JSON.
почему бы просто не использовать атрибут pos
JSONDecodeError
, чтобы сказать вам, где разграничивать вещи?
что-то типа:
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)
Вставьте образец вашего файла вместе с тем, как вы хотели бы получить вывод.