Несколько объектов 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