解析大型JSON文件

18

我正在编写一个cron脚本,它会调用一个API,接收JSON文件(一个大数组的对象)并将其存储在本地。完成后,另一个脚本需要解析已下载的JSON文件,并将每个对象插入到MySQL数据库中。

我目前使用file_get_contents()json_decode()。这将尝试在处理之前将整个文件读入内存。这是可以接受的,但我的JSON文件通常会范围从250MB-1GB+。我知道我可以增加PHP内存限制,但在我看来这不是最好的答案。我知道可以运行fopen()fgets()逐行读取文件,但我需要按每个JSON对象逐个读取文件。

是否有一种方法按对象读取文件,或者是否有另一种类似的方法?


2
这篇帖子可能会对你有所帮助... - user1646111
为什么JSON文件这么大? - Wayne Whitty
4
天哪!API调用返回1GB的数据?那太不可思议了。开发者从来没听说过分页的概念吗? - Spudley
2
如果JSON文件是数据库转储文件,那么应该有其他解决办法.. - Gntem
为此,我建议使用 CSV 文件,一行一个对象,因此流式处理文件的技术可以很好地工作。 - santiago arizti
显示剩余3条评论
3个回答

10

尝试使用这个库 https://github.com/shevron/ext-jsonreader

现有的 PHP 所附带的 ext/json 库非常方便和易于使用——但是,当处理大量的 JSON 数据时,它在效率上存在不足,因为它需要将整个 JSON 数据一次性读入内存(例如使用 file_get_contents()),然后将其转换为 PHP 变量——对于大数据集,这会占用很多内存。

JSONReader 专为内存效率而设计——它适用于流,并且可以从任何 PHP 流中读取 JSON 数据而无需将所有数据加载到内存中。它还允许开发人员从 JSON 流中提取特定的值,而无需解码和将所有数据加载到内存中。


6
这真的取决于json文件包含什么内容。如果一次性将文件打开到内存中不可行,您唯一的选择就是使用fopen/fgets,正如您所暗示的那样。逐行读取是可能的,如果这些json对象具有一致的结构,则可以轻松检测到文件中json对象的开始和结束。收集整个对象后,将其插入到数据库中,然后继续下一个对象。没有更多的内容了。检测json对象的开始和结束的算法可能会因数据源而变得复杂,但我以前使用过更复杂的结构(xml)进行过类似的操作,并且效果很好。

结构非常基础,一个大的对象数组,每个对象都有相同的三个属性。我假设我会使用 fgets() 函数,解析每个字符串以查找其中的所有 JSON 对象,并将它们插入到数据库中。然后,我将重置指针到最后一个成功找到的 JSON 对象的末尾并重复此过程。这是你想要的吗? - Dan Ramos
没错。由于文件大小差异较大(200mb 到 1gb 等等),最好采用一种不受文件大小影响的方法来处理。 - Kovo

3

最佳解决方案:

使用某种分隔符(分页、时间戳、对象ID等),允许您在多个请求中将数据读取为较小的块。此解决方案假定您在生成这些JSON文件方面具有某种控制权。我基于以下假设:

这很好,但问题在于我的 JSON 文件通常会在250MB-1GB+之间。

读取和处理1GB的JSON数据非常荒谬。需要更好的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接