我知道已经提到了JSON流解析器https://github.com/salsify/jsonstreamingparser。但是,由于我最近添加了一个新的监听器,试图使它更容易使用,所以我想(换个口味)发布一些关于它的信息...
有一篇非常好的基本解析器介绍文章https://www.salsify.com/blog/engineering/json-streaming-parser-for-php,但我对标准设置的问题是,您总是需要编写一个监听器来处理文件。这并不总是一项简单的任务,如果/当JSON发生更改时,还需要进行一定的维护。因此,我编写了RegexListener
。
基本原则是允许您通过正则表达式说出您感兴趣的元素,并给它一个回调函数来告诉它在找到数据时要做什么。在读取JSON时,它会跟踪每个组件的路径-类似于目录结构。因此,对于数组,例如
/items/item/2/partid
或
/name/forename
- 这就是正则表达式所匹配的内容。
一个例子是(来自
github上的源代码)...
$filename = __DIR__.'/../tests/data/example.json';
$listener = new RegexListener([
'/1/name' => function ($data): void {
echo PHP_EOL."Extract the second 'name' element...".PHP_EOL;
echo '/1/name='.print_r($data, true).PHP_EOL;
},
'(/\d*)' => function ($data, $path): void {
echo PHP_EOL."Extract each base element and print 'name'...".PHP_EOL;
echo $path.'='.$data['name'].PHP_EOL;
},
'(/.*/nested array)' => function ($data, $path): void {
echo PHP_EOL."Extract 'nested array' element...".PHP_EOL;
echo $path.'='.print_r($data, true).PHP_EOL;
},
]);
$parser = new Parser(fopen($filename, 'r'), $listener);
$parser->parse();
只是一些解释...
'/1/name' => function ($data)
因此,/1
是数组中的第二个元素(基于0),这允许访问特定实例的元素。/name
是 name
元素。然后将该值作为 $data
传递给闭包。
"(/\d*)" => function ($data, $path )
这将选择数组的每个元素并逐个传递,因为它使用了一个捕获组,所以这些信息将作为$path
传递。这意味着当文件中存在一组记录时,您可以逐个处理每个项目。而且不必跟踪就能知道哪个元素。
最后一个
'(/.*/nested array)' => function ($data, $path):
有效地扫描任何名为嵌套数组
的元素,并将每个元素以及其在文档中的位置传递。
我发现另一个有用的功能是,如果在大型JSON文件中,您只想要顶部的摘要信息,您可以获取这些信息,然后停止...
$filename = __DIR__.'/../tests/data/ratherBig.json';
$listener = new RegexListener();
$parser = new Parser(fopen($filename, 'rb'), $listener);
$listener->setMatch(["/total_rows" => function ($data ) use ($parser) {
echo "/total_rows=".$data.PHP_EOL;
$parser->stop();
}]);
当你对剩余的内容不感兴趣时,这可以节省时间。
需要注意的是,这些会根据内容做出反应,所以每个元素在找到与之匹配的结束内容时会被触发,并且可能以各种顺序出现。但同时解析器只会跟踪你感兴趣的内容,并且舍弃其他任何内容。
如果你发现任何有趣的特性(有时候也被称为bug),请告诉我或在GitHub页面上报告一个问题。