Несколько объектов Json в одном файле извлечения python
Я очень новичок в Json файлах. Если у меня есть json файл с несколькими объектами json, например:
{"ID":"12345","Timestamp":"20140101", "Usefulness":"Yes",
"Code":[{"event1":"A","result":"1"},…]}
{"ID":"1A35B","Timestamp":"20140102", "Usefulness":"No",
"Code":[{"event1":"B","result":"1"},…]}
{"ID":"AA356","Timestamp":"20140103", "Usefulness":"No",
"Code":[{"event1":"B","result":"0"},…]}
…
Я хочу извлечь все временные метки и "Полезность" в кадры данных:
Timestamp Usefulness
0 20140101 Yes
1 20140102 No
2 20140103 No
…
Кто-нибудь знает общий способ справиться с такими проблемами? Спасибо!
Ответы
Ответ 1
Используйте массив json в формате:
[
{"ID":"12345","Timestamp":"20140101", "Usefulness":"Yes",
"Code":[{"event1":"A","result":"1"},…]},
{"ID":"1A35B","Timestamp":"20140102", "Usefulness":"No",
"Code":[{"event1":"B","result":"1"},…]},
{"ID":"AA356","Timestamp":"20140103", "Usefulness":"No",
"Code":[{"event1":"B","result":"0"},…]},
...
]
Затем импортируйте его в свой код Python
import json
with open('file.json') as json_file:
data = json.load(json_file)
Теперь содержимое данных представляет собой массив со словарями, представляющими каждый из элементов.
Вы можете легко получить к нему доступ, т.е.
data[0]["ID"]
Ответ 2
Вы можете использовать json.JSONDecoder.raw_decode
для декодирования произвольно больших строк "сложного" JSON (до тех пор, пока они могут поместиться в память). raw_decode
останавливается, когда у него есть действительный объект, и возвращает последнюю позицию, которая не была частью анализируемого объекта. Он не задокументирован, но вы можете передать эту позицию обратно в raw_decode
и снова начать синтаксический анализ этой позиции. К сожалению, модуль json
Python не принимает строки с префиксом пробелов. Поэтому нам нужно выполнить поиск, чтобы найти первую часть без пробелов вашего документа.
from json import JSONDecoder, JSONDecodeError
import re
NOT_WHITESPACE = re.compile(r'[^\s]')
def decode_stacked(document, pos=0, decoder=JSONDecoder()):
while True:
match = NOT_WHITESPACE.search(document, pos)
if not match:
return
pos = match.start()
try:
obj, pos = decoder.raw_decode(document, pos)
except JSONDecodeError:
# do something sensible if there some error
raise
yield obj
s = """
{"a": 1}
[
1
,
2
]
"""
for obj in decode_stacked(s):
print(obj)
печатает:
{'a': 1}
[1, 2]
Ответ 3
Итак, как упоминалось в парах комментариев, содержащих данные в массиве, проще, но решение не масштабируется с точки зрения эффективности по мере увеличения размера набора данных. Вы действительно должны использовать только итератор, когда хотите получить доступ к случайному объекту в массиве, иначе генераторы - это путь. Ниже я создал прототип функции чтения, которая считывает каждый json-объект по отдельности и возвращает генератор.
Основная идея - сигнализировать читателю о разделении символа каретки "\n" (или "\ r\n" для Windows). Python может сделать это с помощью функции file.readline().
import json
def json_readr(file):
for line in open(file, mode="r"):
yield json.loads(line)
Однако этот метод работает только тогда, когда файл написан так, как он есть, - с каждым объектом, разделенным новым символом строки. Ниже я написал пример автора, который отделяет массив объектов json и сохраняет каждый в новой строке.
def json_writr(file, json_objects):
f = open(file, mode="w")
for jsonobj in json_objects:
jsonstr = json.dumps(jsonobj)
f.write(jsonstr+"\n")
f.flush()
f.close()
Вы также можете выполнить ту же операцию с file.writelines() и пониманием списка
...
jsobjs = [json.dumps(j)+"\n" for j in json_objects]
f.writelines(jsobjs)
...
И если вы хотите добавить данные вместо записи нового файла, просто измените 'mode =' w "'to' mode =" a ".
В конце концов, я нахожу, что это очень помогает не только с читабельностью, когда я пытаюсь открыть json файлы в текстовом редакторе, но и с точки зрения использования памяти более эффективно.
В этой заметке, если вы передумаете в какой-то момент, и вы хотите, чтобы список не читался, Python позволяет вам поместить функцию генератора внутри списка и автоматически заполнить список. Другими словами, просто напишите
lst = list(json_readr(file))
Надеюсь, это поможет. Извините, если это было немного многословно.
Ответ 4
Когда вы анализируете объекты, вы имеете дело со словарями. Вы можете извлечь нужные значения, выполнив поиск по клавише. Например. value = jsonDictionary['Usefulness']
.
Вы можете прокручивать объекты json
с помощью цикла for. например:.
for obj in bunchOfObjs:
value = obj['Usefulness']
#now do something with your value, e.g insert into panda....
Ответ 5
Добавлена поддержка потоковой передачи на основе ответа @dunes:
import re
from json import JSONDecoder, JSONDecodeError
NOT_WHITESPACE = re.compile(r"[^\s]")
def stream_json(file_obj, buf_size=1024, decoder=JSONDecoder()):
buf = ""
ex = None
while True:
block = file_obj.read(buf_size)
if not block:
break
buf += block
pos = 0
while True:
match = NOT_WHITESPACE.search(buf, pos)
if not match:
break
pos = match.start()
try:
obj, pos = decoder.raw_decode(buf, pos)
except JSONDecodeError as e:
ex = e
break
else:
ex = None
yield obj
buf = buf[pos:]
if ex is not None:
raise ex