我正在尝试处理一些较大(可能高达 200M)的 JSON 文件。文件的结构基本上是一个对象数组。
所以类似于:
[ {"property":"value", "property2":"value2"}, {"prop":"val"}, ... {"foo":"bar"} ]
每个对象都具有任意属性,并且不必与数组中的其他对象共享它们(如,具有相同)。
我想对数组中的每个对象进行处理,并且由于文件可能很大,因此我无法将整个文件内容存储在内存中,无法解码 JSON 并遍历 PHP 数组。
所以理想情况下我想读取文件,为每个对象获取足够的信息并处理它。如果有可用于 JSON 的类似库,那么 SAX 类型的方法就可以了。
关于如何最好地处理这个问题的任何建议?
它与基于事件的解析器显着不同之处在于,您无需设置回调并让解析器完成其工作,而是调用解析器上的方法以根据需要移动或检索数据。找到您想要的位并想停止解析?然后停止解析(并调用close(),因为这是一件好事。)
close()
(有关拉取解析器与基于事件的解析器的稍长概述,请参阅XML 阅读器模型:SAX 与 XML 拉取解析器。)
从 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 )
对象作为字符串键数组返回(部分)是由于有效 JSON 会产生 PHP 对象中不允许的属性名称的边缘情况。解决这些冲突是不值得的,因为贫血的 stdClass 对象无论如何都不会为简单的数组带来任何价值。
分别读取每个命名元素。
$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
读取给定名称的每个属性。奖励:从字符串而不是 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 取决于它的结构和你想用它做什么。这些示例应该为您提供一个起点。