在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器的工作原理。