Парсинг неправильного JSON | Python
Имеется вот такая неправильная выгруженная коллекция из MongoDB:
"title": "Инструкция конец"
"createdBy": "[email protected]"
"dateCreated": ISODate("2022-08-03T12:14:09.881+0000")
"fileName": "Инструкция конец.docx"
"title": "Blueprint"
"createdBy": "[email protected]"
"dateCreated": ISODate("2022-08-03T11:59:03.109+0000")
"fileName": "Blueprint.pdf"
"title": "Contract"
"createdBy": "[email protected]"
"dateCreated": ISODate("2022-08-03T11:59:03.552+0000")
"fileName": "Contract.docx"
"title": "Marketing report"
"createdBy": "[email protected]"
"dateCreated": ISODate("2022-08-03T11:59:03.755+0000")
"fileName": "Marketing report.pptx"
"title": "Blueprint"
Легко открывается вот так:
with open('C:\base.json', "r", encoding="utf8") as file:
Нативным JSON, разумеется, не является. По сути это простой TXT. Нужно получить полную выборку, желательно в виде табличного файла, например, CSV. Требуются все(4) "ключи" и из значения:
"dateCreated": | "fileName" | "title": | "createdBy":
Будет круто, если можно будет присвоить свои ключи и подставить к ним значения, чтобы получилось подобное:
Буду благодарен, если подскажите, как лучше реализовать. Получится ли такое вообще в нормальный словарь преобразовать с небольшими усилиями?
Ответы (1 шт):
Не надо называть json то что json не является. Но опустим пока эту несуразицу.
То что не парсит json, обычно довольно неплохо парсит yaml:
import yaml
d = {}
with open('base.json', "r", encoding="utf8") as f:
for line in f:
for k,v in yaml.safe_load(line).items():
d.setdefault(k,[]).append(v)
Переменная d:
{'title': ['Инструкция конец',
'Blueprint',
'Contract',
'Marketing report',
'Blueprint'],
'createdBy': ['[email protected]', '[email protected]', '[email protected]', '[email protected]'],
'dateCreated': ['ISODate("2022-08-03T12:14:09.881+0000")',
'ISODate("2022-08-03T11:59:03.109+0000")',
'ISODate("2022-08-03T11:59:03.552+0000")',
'ISODate("2022-08-03T11:59:03.755+0000")'],
'fileName': ['Инструкция конец.docx',
'Blueprint.pdf',
'Contract.docx',
'Marketing report.pptx']}
В таблицу
Получили довольно внятный словарь, который теперь можно запихнуть в pandas. Ну почти. В приведённом примере последнему title (Blueprint) нет соответствующих строк в других колонках, DataFrame так не собрать. Надеюсь у тебя данные более полные.
Но пока на данном этапе уберём данную оплошность:
max_rows = max(len(l) for l in d.values())
for v in d.values():
while len(v) < max_rows:
v.append(None)
Отлично, теперь можно собрать DataFrame.
import pandas as pd
df = pd.DataFrame.from_dict(d)
# Приводим колонку с датой к datetime
df['dateCreated'] = pd.to_datetime(df.dateCreated.str.replace(r'.*\("|"\)',''))
# Переименовываем колонки
df = df.rename(columns={'title': 'Заголовок',
'createdBy': 'Загрузил',
'dateCreated': 'Дата загрузки',
'fileName': 'Название файла'})
# Сортируем колонки
cols = df.columns.tolist()
cols = cols[-2:] + cols[:2]
df = df[cols]
# Длинную дату вида "2022-08-03 12:14:09.881000+00:00" приводим к короткому варианту
df['Дата загрузки'] = df['Дата загрузки'].dt.date
print(df)
Вывод:
Дата загрузки Название файла Заголовок Загрузил
0 2022-08-03 Инструкция конец.docx Инструкция конец [email protected]
1 2022-08-03 Blueprint.pdf Blueprint [email protected]
2 2022-08-03 Contract.docx Contract [email protected]
3 2022-08-03 Marketing report.pptx Marketing report [email protected]
4 NaT None Blueprint None
Дальше DataFrame можно сохранить в csv одной строчкой:
df.to_csv('out.csv', index=False)
Вместо csv можно сохранить в excel:
df.to_excel("out.xlsx")
