在PHP中处理大型的JSON文件

我正在尝试处理有些大(可能高达200M)的JSON文件。 该文件的结构基本上是一个对象的数组。

所以有如下几点:

[ {"property":"value", "property2":"value2"}, {"prop":"val"}, ... {"foo":"bar"} ] 

每个对象都具有任意的属性,并且不需要与数组中的其他对象共享它们(如同样具有相同的属性)。

我想对数组中的每个对象应用一个处理,并且由于这个文件可能很大,所以我不能在内存中search整个文件内容,解码JSON并遍历PHP数组。

所以理想情况下,我想读取文件,为每个对象获取足够的信息并处理它。 如果有类似的JSON库可用,SAXtypes的方法可以。

任何build议如何处理这个问题最好?

我决定在基于事件的parsing器上工作。 目前还没有完成,当我推出一个令人满意的版本时,将编辑与我的工作链接的问题。

编辑:

我终于找出了一个我满意的parsing器版本。 它在GitHub上可用:

https://github.com/kuma-giyomu/JSONParser

有可能有一些改善的空间,并欢迎反馈。

我已经为基于XMLReader的api编写了一个stream式JSONparsing器pcrov / JsonReader for PHP 7。

它与基于事件的parsing器有很大的不同,它不是设置callback并让parsing器完成它的工作,而是调用parsing器上的方法来根据需要移动或检索数据。 find你想要的位,并想停止parsing? 然后停止parsing(并调用close()因为这是件好事。)

(有关pull和基于事件的parsing器的略微更长的概述,请参阅XML读取器模型:SAX和XML pullparsing器 。


例1:

从您的JSON中读取每个对象作为一个整体。

 use pcrov\JsonReader\JsonReader; $reader = new JsonReader(); $reader->open("data.json"); $reader->read(); // Outer array. $depth = $reader->depth(); // Check in a moment to break when the array is done. $reader->read(); // Step to the first object. do { print_r($reader->value()); // Do your thing. } while ($reader->next() && $reader->depth() > $depth); // Read each sibling. $reader->close(); 

输出:

 Array ( [property] => value [property2] => value2 ) Array ( [prop] => val ) Array ( [foo] => bar ) 

对象返回为string键控数组,这是因为(部分)由于有效的JSON会产生PHP对象中不允许的属性名称的边缘情况。 解决这些冲突是不值得的,因为stdClass对象无论如何都不会为简单的数组带来任何价值。


例2:

分别读取每个指定的元素。

 $reader = new pcrov\JsonReader\JsonReader(); $reader->open("data.json"); while ($reader->read()) { $name = $reader->name(); if ($name !== null) { echo "$name: {$reader->value()}\n"; } } $reader->close(); 

输出:

 property: value property2: value2 prop: val foo: bar 

例3:

阅读给定名称的每个属性。 奖金:从string中读取而不是从URI中读取,同时在同一个对象中获取具有重复名称的属性的数据(这在JSON中是允许的,有趣)。

 $json = <<<'JSON' [ {"property":"value", "property2":"value2"}, {"foo":"foo", "foo":"bar"}, {"prop":"val"}, {"foo":"baz"}, {"foo":"quux"} ] JSON; $reader = new pcrov\JsonReader\JsonReader(); $reader->json($json); while ($reader->read("foo")) { echo "{$reader->name()}: {$reader->value()}\n"; } $reader->close(); 

输出:

 foo: foo foo: bar foo: baz foo: quux 

如何最好地阅读你的JSON取决于它的结构和你想要做什么。 这些例子应该给你一个开始的地方。

存在这样的东西,但只适用于C ++和Java 。 除非您可以从PHP访问这些库中的一个,否则在PHP中没有这个实现,但是据我所知json_read() 。 但是,如果json的结构很简单,那么直到下一个}才能读取文件,然后处理通过json_read()接收到的JSON。 但是你最好还是这样做,比如读取10kb,如果没有find,再读取10k,然后处理find的值。 然后阅读下一个块等。

这是一个简单的stream式parsing器,用于处理大型的JSON文档。 使用它来parsing非常大的JSON文件,以避免将整个东西加载到内存中,这就是PHP的其他每个JSONparsing器的工作原理。

https://github.com/salsify/jsonstreamingparser