Ivá*_*rez 11 php json yield generator
我有一个非常大的PHP(5.6)数组,动态生成,我想转换为JSON.问题是数组太大而不适合内存 - 当我尝试处理它(耗尽的内存)时会出现致命的错误.所以我发现,使用发生器,内存问题将消失.
这是我到目前为止尝试过的代码(这个简化示例显然不会产生内存错误):
<?php
function arrayGenerator()// new way using generators
{
for ($i = 0; $i < 100; $i++) {
yield $i;
}
}
function getArray()// old way, generating and returning the full array
{
$array = [];
for ($i = 0; $i < 100; $i++) {
$array[] = $i;
}
return $array;
}
$object = [
'id' => 'foo',
'type' => 'blah',
'data' => getArray(),
'gen' => arrayGenerator(),
];
echo json_encode($object);
Run Code Online (Sandbox Code Playgroud)
但PHP似乎没有对生成器中的值进行JSON编码.这是我从previuos脚本得到的输出:
{
"id": "foo",
"type": "blah",
"data": [// old way - OK
0,
1,
2,
3,
//...
],
"gen": {}// using generator - empty object!
}
Run Code Online (Sandbox Code Playgroud)
在调用之前,甚至可以对生成器生成的数组进行JSON编码而不生成完整序列json_encode
吗?
不幸的是,json_encode无法从生成器函数生成结果.使用iterator_to_array
仍然会尝试创建整个数组,这仍然会导致内存问题.
您将需要创建将从生成器函数生成json字符串的函数.这是一个如何看起来的例子:
function json_encode_generator(callable $generator) {
$result = '[';
foreach ($generator as $value) {
$result .= json_encode($value) . ',';
}
return trim($result, ',') . ']';
}
Run Code Online (Sandbox Code Playgroud)
它不是一次编码整个数组,而是一次只编码一个对象,并将结果连接成一个字符串.
上面的例子只负责编码数组,但它可以很容易地扩展为递归编码整个对象.
如果创建的字符串仍然太大而无法容纳在内存中,那么您唯一剩下的选项是直接使用输出流.这是看起来如何:
function json_encode_generator(callable $generator, $outputStream) {
fwrite($outputStream, '[');
foreach ($generator as $key => $value) {
if ($key != 0) {
fwrite($outputStream, ',');
}
fwrite($outputStream, json_encode($value));
}
fwrite($outputStream, ']');
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,唯一的区别是我们现在fwrite
用来写入传入的流而不是连接字符串,我们还需要以不同的方式处理尾随逗号.
归档时间: |
|
查看次数: |
2945 次 |
最近记录: |