将 JSON 字符串转换为不带 json_decode 的数组
Convert JSON string to array WITHOUT json_decode
我在共享服务器上使用 PHP 通过 API 访问外部站点,即 returning JSON 包含 2 级数据(第 1 级:表演者 &级别 2:执行者内部的类别数组)。我想在不使用 json_decode 函数的情况下将其转换为多维关联数组(它为此使用了太多内存!!!)
JSON 数据示例:
[
{
"performerId": 99999,
"name": " Any performer name",
"category": {
"categoryId": 99,
"name": "Some category name",
"eventType": "Category Event"
},
"eventType": "Performer Event",
"url": "http://www.novalidsite.com/something/performerspage.html",
"priority": 0
},
{
"performerId": 88888,
"name": " Second performer name",
"category": {
"categoryId": 88,
"name": "Second Category name",
"eventType": "Category Event 2"
},
"eventType": "Performer Event 2",
"url": "http://www.novalidsite.com/somethingelse/performerspage2.html",
"priority": 7
}
]
我尝试使用 substr 并去掉“[”和“]”。
然后执行调用:
preg_match_all('/\{([^}]+)\}/', $input, $matches);
这为我提供了每行的字符串,但在类别数据的尾随“}”之后被截断了。
我如何使用 preg_split、preg_match_all 等方法 return 将整行数据作为数组来代替 json_decode 等繁重的调用在整个 JSON 字符串上?
一旦我正确识别了每一行的数组,我就可以在该字符串上执行 json_decode 而不会过度占用共享服务器上的内存。
对于那些想要了解有关 json_decode 使用导致错误的更多详细信息的人:
$aryPerformersfile[ ] = file_get_contents('https://subdomain.domain.com/dir/getresults?id=1234');
$aryPerformers = $aryPerformersfile[0];
unset($aryPerformersfile);
$mytmpvar = json_decode($aryPerformers);
print_r($mytmpvar);
exit;
这里你有两个选择,但都不包括你自己写解码器;不要用不必要的解决方法使解决方案过于复杂。
1) 减小正在解码的 json 的大小,或者
2) 增加服务器允许的内存。
第一个选项需要访问正在创建的 json。这可能会也可能不会,具体取决于您是否是最初创建 json 的人。最简单的方法是 unset()
任何无用的数据。例如,可能有一些您不需要的调试信息,因此您可以对无用数据执行 unset($json_array['debug']);
。
http://php.net/manual/en/function.unset.php
第二个选项要求您有权访问服务器上的 php.ini 文件。您需要找到类似 memory_limit = 128M
的行,并使 128M
部分变大。尝试增加它以将文件中已有的值加倍(因此在本例中为 256M)。但这可能无法解决您的问题,因为大型 json 数据仍然可能是您问题的核心;这只是为低效代码提供了一种解决方法。
如果您的内存量有限,您可以将数据作为流读取并一次解析 JSON 一个片段,而不是一次解析所有内容。
getresults.json:
[
{
"performerId": 99999,
"name": " Any performer name",
"category": {
"categoryId": 99,
"name": "Some category name",
"eventType": "Category Event"
},
"eventType": "Performer Event",
"url": "http://www.novalidsite.com/something/performerspage.html",
"priority": 0
},
{
"performerId": 88888,
"name": " Second performer name",
"category": {
"categoryId": 88,
"name": "Second Category name",
"eventType": "Category Event 2"
},
"eventType": "Performer Event 2",
"url": "http://www.novalidsite.com/somethingelse/performerspage2.html",
"priority": 7
}
]
PHP:
$stream = fopen('getresults.json', 'rb');
// Read one character at a time from $stream until
// $count number of $char characters is read
function readUpTo($stream, $char, $count)
{
$str = '';
$foundCount = 0;
while (!feof($stream)) {
$readChar = stream_get_contents($stream, 1);
$str .= $readChar;
if ($readChar == $char && ++$foundCount == $count)
return $str;
}
return false;
}
// Read one JSON performer object
function readOneJsonPerformer($stream)
{
if ($json = readUpTo($stream, '{', 1))
return '{' . readUpTo($stream, '}', 2);
return false;
}
while ($json = readOneJsonPerformer($stream)) {
$performer = json_decode($json);
echo 'Performer with ID ' . $performer->performerId
. ' has category ' . $performer->category->name, PHP_EOL;
}
fclose($stream);
输出:
Performer with ID 99999 has category Some category name
Performer with ID 88888 has category Second Category name
当然可以通过使用缓冲区来加快读取速度来改进此代码,考虑到字符串值本身可能包括 {
和 }
字符等
我在共享服务器上使用 PHP 通过 API 访问外部站点,即 returning JSON 包含 2 级数据(第 1 级:表演者 &级别 2:执行者内部的类别数组)。我想在不使用 json_decode 函数的情况下将其转换为多维关联数组(它为此使用了太多内存!!!)
JSON 数据示例:
[
{
"performerId": 99999,
"name": " Any performer name",
"category": {
"categoryId": 99,
"name": "Some category name",
"eventType": "Category Event"
},
"eventType": "Performer Event",
"url": "http://www.novalidsite.com/something/performerspage.html",
"priority": 0
},
{
"performerId": 88888,
"name": " Second performer name",
"category": {
"categoryId": 88,
"name": "Second Category name",
"eventType": "Category Event 2"
},
"eventType": "Performer Event 2",
"url": "http://www.novalidsite.com/somethingelse/performerspage2.html",
"priority": 7
}
]
我尝试使用 substr 并去掉“[”和“]”。
然后执行调用:
preg_match_all('/\{([^}]+)\}/', $input, $matches);
这为我提供了每行的字符串,但在类别数据的尾随“}”之后被截断了。
我如何使用 preg_split、preg_match_all 等方法 return 将整行数据作为数组来代替 json_decode 等繁重的调用在整个 JSON 字符串上?
一旦我正确识别了每一行的数组,我就可以在该字符串上执行 json_decode 而不会过度占用共享服务器上的内存。
对于那些想要了解有关 json_decode 使用导致错误的更多详细信息的人:
$aryPerformersfile[ ] = file_get_contents('https://subdomain.domain.com/dir/getresults?id=1234');
$aryPerformers = $aryPerformersfile[0];
unset($aryPerformersfile);
$mytmpvar = json_decode($aryPerformers);
print_r($mytmpvar);
exit;
这里你有两个选择,但都不包括你自己写解码器;不要用不必要的解决方法使解决方案过于复杂。
1) 减小正在解码的 json 的大小,或者 2) 增加服务器允许的内存。
第一个选项需要访问正在创建的 json。这可能会也可能不会,具体取决于您是否是最初创建 json 的人。最简单的方法是 unset()
任何无用的数据。例如,可能有一些您不需要的调试信息,因此您可以对无用数据执行 unset($json_array['debug']);
。
http://php.net/manual/en/function.unset.php
第二个选项要求您有权访问服务器上的 php.ini 文件。您需要找到类似 memory_limit = 128M
的行,并使 128M
部分变大。尝试增加它以将文件中已有的值加倍(因此在本例中为 256M)。但这可能无法解决您的问题,因为大型 json 数据仍然可能是您问题的核心;这只是为低效代码提供了一种解决方法。
如果您的内存量有限,您可以将数据作为流读取并一次解析 JSON 一个片段,而不是一次解析所有内容。
getresults.json:
[
{
"performerId": 99999,
"name": " Any performer name",
"category": {
"categoryId": 99,
"name": "Some category name",
"eventType": "Category Event"
},
"eventType": "Performer Event",
"url": "http://www.novalidsite.com/something/performerspage.html",
"priority": 0
},
{
"performerId": 88888,
"name": " Second performer name",
"category": {
"categoryId": 88,
"name": "Second Category name",
"eventType": "Category Event 2"
},
"eventType": "Performer Event 2",
"url": "http://www.novalidsite.com/somethingelse/performerspage2.html",
"priority": 7
}
]
PHP:
$stream = fopen('getresults.json', 'rb');
// Read one character at a time from $stream until
// $count number of $char characters is read
function readUpTo($stream, $char, $count)
{
$str = '';
$foundCount = 0;
while (!feof($stream)) {
$readChar = stream_get_contents($stream, 1);
$str .= $readChar;
if ($readChar == $char && ++$foundCount == $count)
return $str;
}
return false;
}
// Read one JSON performer object
function readOneJsonPerformer($stream)
{
if ($json = readUpTo($stream, '{', 1))
return '{' . readUpTo($stream, '}', 2);
return false;
}
while ($json = readOneJsonPerformer($stream)) {
$performer = json_decode($json);
echo 'Performer with ID ' . $performer->performerId
. ' has category ' . $performer->category->name, PHP_EOL;
}
fclose($stream);
输出:
Performer with ID 99999 has category Some category name
Performer with ID 88888 has category Second Category name
当然可以通过使用缓冲区来加快读取速度来改进此代码,考虑到字符串值本身可能包括 {
和 }
字符等