Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从一个文件中提取多个JSON对象?_Python_Json_Pandas_Dataframe_Parsing - Fatal编程技术网

Python 如何从一个文件中提取多个JSON对象?

Python 如何从一个文件中提取多个JSON对象?,python,json,pandas,dataframe,parsing,Python,Json,Pandas,Dataframe,Parsing,我对Json文件非常陌生。如果我有一个包含多个json对象的json文件,例如: {“ID”:“12345”,“时间戳”:“20140101”,“有用性”:“是”, “代码”:[{“事件1”:“A”,“结果”:“1”},…]} {“ID”:“1A35B”,“时间戳”:“20140102”,“有用性”:“否”, “代码”:[{“事件1”:“B”,“结果”:“1”},…]} {“ID”:“AA356”,“时间戳”:“20140103”,“有用性”:“否”, “代码”:[{“event1”:“B”,“

我对Json文件非常陌生。如果我有一个包含多个json对象的json文件,例如:

{“ID”:“12345”,“时间戳”:“20140101”,“有用性”:“是”,
“代码”:[{“事件1”:“A”,“结果”:“1”},…]}
{“ID”:“1A35B”,“时间戳”:“20140102”,“有用性”:“否”,
“代码”:[{“事件1”:“B”,“结果”:“1”},…]}
{“ID”:“AA356”,“时间戳”:“20140103”,“有用性”:“否”,
“代码”:[{“event1”:“B”,“结果”:“0”},…]}
…
我想将所有“时间戳”和“有用性”提取到数据帧中:

时间戳有用性
0 20140101是
20140102号
2 20140103号
…

有人知道处理此类问题的一般方法吗?

使用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"]

因此,正如在几条注释中提到的,在数组中包含数据更简单,但随着数据集大小的增加,解决方案在效率方面不能很好地扩展。当您想要访问数组中的随机对象时,您确实应该只使用迭代器,否则,生成器就是最好的选择。下面我已经原型化了一个reader函数,它分别读取每个json对象并返回一个生成器

其基本思想是向读取器发送信号,让其在回车符上拆分
“\n”
(或Windows的
“\r\n”
)。Python可以通过函数实现这一点

import json
def json_reader(filename):
    with open(filename) as f:
        for line in f:
            yield json.loads(line)
然而,这种方法只有在文件按原样编写时才真正起作用——每个对象由换行符分隔。下面我编写了一个writer示例,它将json对象数组分隔开来,并将每个对象保存在新行中

def json_writer(file, json_objects):
    with open(file, "w") as f:
        for jsonobj in json_objects:
            jsonstr = json.dumps(jsonobj)
            f.write(jsonstr + "\n")
您还可以使用和列表理解执行相同的操作:

...
    json_strs = [json.dumps(j) + "\n" for j in json_objects]
    f.writelines(json_strs)
...
如果您想附加数据而不是编写新文件,只需将
open(file,“w”)
更改为
open(file,“a”)

最后,我发现这不仅有助于提高在文本编辑器中打开json文件时的可读性,而且还能更有效地使用内存

在这一点上,如果您在某个时候改变了主意,并且希望从读取器中得到一个列表,Python允许您在列表中放置一个生成器函数,并自动填充列表。换言之,只要写

lst = list(json_reader(file))

更新:我写了一个解决方案,不需要一次性读取整个文件。它对于stackoverflow答案来说太大了,但是可以在这里找到

您可以使用
json.JSONDecoder.raw_decode
对“堆叠”json的任意大字符串进行解码(只要它们可以放入内存中)
raw_decode
一旦拥有有效对象,就会停止,并返回最后一个不属于已解析对象的位置。它没有文档记录,但您可以将此位置传递回
raw\u 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]

根据@dunes的答案添加了流媒体支持:

重新导入
从json导入JSONDecoder,JSONDecodeError
NOT_WHITESPACE=re.compile(r“[^\s]”)
def stream_json(文件_obj,buf_size=1024,解码器=JSONDecoder()):
buf=“”
ex=无
尽管如此:
块=文件对象读取(大小)
如果不阻止:
打破
buf+=块
pos=0
尽管如此:
匹配=不包含空格。搜索(buf,pos)
如果不匹配:
打破
pos=match.start()
尝试:
obj,pos=解码器。原始解码(buf,pos)
除了JSONDecodeError作为e:
ex=e
打破
其他:
ex=无
产量目标
buf=buf[pos:]
如果ex不是无:
加薪

拥有一个包含所有json对象的json数组将非常容易。这很酷,但会阻止您将文件用作无穷无尽的流(例如,类似于日志的只追加文件数据),并消耗更多内存。@exa,这是真的,但如果您需要只追加此数据流的日志,也许您应该使用JSON以外的格式来传输信息,因为JSON需要所有数据结构的右括号,这意味着非无限非流格式,除了几件事之外,这个答案非常类似:它需要将整个文件读入内存,并使用
JSONDecoder
的未记录功能。仅供参考:对于非空白字符有一个简单的转义:
\S
。大写变量是小写变量的否定形式(因此
\W=[^\W]
\D=[^\D]
ecc)。如果文件具有单行多JSON文件,则这适用于AWS Lambda。。你能更详细地解释一下这是怎么回事吗?我无法理解raw_decode,也无法理解它如何理解有效的json何时开始或结束