【问题标题】:Convert JSON string to array WITHOUT json_decode将 JSON 字符串转换为没有 json_decode 的数组
【发布时间】:2015-02-27 19:33:42
【问题描述】:

我在共享服务器上使用 PHP 通过 API 访问外部站点,该 API 返回包含 2 级数据的 JSON(级别 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 等方法将整行数据作为数组返回。代替整个 JSON 字符串上的 json_decode 等繁重的调用?

一旦我正确识别了每一行的数组,我就可以在该字符串上执行 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;

【问题讨论】:

  • 因此,与其使用 json_decode,不如说您无疑是在调用一种效率较低的解决方法。是的。那会游泳的。 @AbraCadaver 查看phantomJS
  • 内存占用过多怎么办?你能告诉我们它是如何使用太多的,你对太多的定义是什么?我的猜测不是该功能使用太多,而是您没有使用unset() 正确收集垃圾,或者您需要增加应用程序中的内存分配
  • 我真的很感兴趣你是如何计算出json_decode 使用too much memory 的?你的json sring有多大? json_decode 在你的情况下需要多少?您使用什么工具来扩展内存使用量?
  • 感谢无证嘲讽。非常感谢!在当前在共享主机上运行 Wordpress(PHP 和 MySQL)的网站上。我进行 API 调用,将 JSON 内容返回到变量中。当我在变量上调用 json_decode 时,我收到以下错误:PHP 致命错误:第 3 行 /home/mysite/public_html/subdir/myfile.php 中允许的内存大小为 134217728 字节已用尽(尝试分配 10 个字节)。

标签: php arrays json preg-match-all preg-split


【解决方案1】:

如果您的内存量有限,您可以将数据作为流读取并一次解析一个 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

这个代码当然可以通过使用缓冲区来提高读取速度,考虑到字符串值本身可能包括 {} 字符等。

【讨论】:

  • 谢谢@mhall!非常感谢
  • 这对我帮助很大。谢谢!对于其他使用它,请务必根据您正在使用的右括号数调整 $count 参数。
【解决方案2】:

这里有两个选择,但都不包括你编写自己的解码器;不要使用不必要的变通方法使解决方案过于复杂。

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 数据无关。该问题可能是由在解码发生之前可能导致的一个大变量引起的,在这种情况下,使解码成为“压垮骆驼的最后一根稻草”。
猜你喜欢
  • 2014-05-16
  • 2018-12-17
  • 2015-01-06
  • 1970-01-01
  • 2020-04-27
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多