一个文件中的多个Json对象由python提取

时间:2015-01-12 17:33:22

标签: python json parsing pandas

我对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
 …

有谁知道处理此类问题的一般方法?谢谢!

5 个答案:

答案 0 :(得分:43)

您可以使用json.JSONDecoder.raw_decode来解码任意大字符串"堆叠" JSON(只要它们可以适合内存)。 raw_decode一旦有了有效对象就停止,并返回最后一个位置,其中isn是解析对象的一部分。它没有记录,但您可以将此位置传回raw_decode,然后从该位置再次开始解析。不幸的是,Python json模块不接受具有前缀空格的字符串。所以我们需要搜索以找到文档的第一个非空白部分。

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's some error
            raise
        yield obj

s = """

{"a": 1}  


   [
1
,   
2
]


"""

for obj in decode_stacked(s):
    print(obj)

打印:

{'a': 1}
[1, 2]

答案 1 :(得分:21)

使用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 :(得分:5)

因此,正如在几个包含数组中的数据的注释中所提到的那样简单,但随着数据集大小的增加,解决方案在效率方面不能很好地扩展。当你想要访问数组中的随机对象时,你真的应该只使用迭代器,否则,生成器是可行的方法。下面我原型了一个reader函数,它单独读取每个json对象并返回一个生成器。

基本思想是通知读者分割托架字符“\ n”(或Windows的“\ r \ n”)。 Python可以使用文件 .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()

您也可以使用文件 .writelines()和列表理解进行相同的操作

...
    jsobjs = [json.dumps(j)+"\n" for j in json_objects]
    f.writelines(jsobjs)
...

如果您想要附加数据而不是写新文件,只需将'mode =“w”'更改为'mode =“a”'。

最后,我发现当我尝试在文本编辑器中打开json文件时,以及在更有效地使用内存方面,这不仅有助于提高可读性。

在那个注意事项中,如果你在某个时候改变了想法,并且想要一个读者列表,那么Python允许你将一个生成器函数放在一个列表中并自动填充列表。换句话说,只需写

lst = list(json_readr(file))

希望这会有所帮助。对不起,如果它有点冗长。

答案 3 :(得分:2)

根据@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

答案 4 :(得分:-2)

在解析对象时,您正在处理字典。您可以通过搜索键来提取所需的值。例如。 value = jsonDictionary['Usefulness']

您可以使用for循环遍历json个对象。 e.g:

for obj in bunchOfObjs:
    value = obj['Usefulness']
    #now do something with your value, e.g insert into panda....