如何将字符串解析为数组PHP

时间:2017-01-26 10:58:33

标签: php json parsing logging

我有一个日志文件,看起来像这样:

[{"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"}]

[{"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"},
 {"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"}]

正如您所看到的那样,它是一组JSON对象。我想解析这个日志,以便能够将它转换回我可以循环的PHP数组。我尝试过使用explode("]", $logContents),但我发现这会干扰数组的内容(因为内容中还包含一个']'字符)。日志文件可能很大(20mb +)因此我不能依赖基于多个字符的爆炸(例如explode("}]", $logContents),因为操作时间太长。我确定必须有一个更简单的方法这!

最后,我想拥有一组JSON日志项的数组。在给定的示例中,我们有一个包含2个数组的数组。第一个数组有1个日志项,第二个数组有2个日志项。

4 个答案:

答案 0 :(得分:0)

尝试使用以下代码:

$j_obj1 = '[{"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"}]';

$j_obj2 = '[{"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"},
 {"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"}]';

$j_arr1 = json_decode($j_obj1, true);
$j_arr2 = json_decode($j_obj2, true);

foreach ($j_arr1 as $data) {
    echo $data['ip']; // You can iterate
}

foreach ($j_arr2 as $data) {
    echo $data['prop1']; // You can iterate
}

答案 1 :(得分:0)

假设文件包含每行有效的JSON,请求的代码片段可能是:

foreach (file($logpath) as $line) {
    $entry = json_decode($line, TRUE);
    foreach ($entry as $item) {
        echo('IP: '.$item['ip'].'; prop1: '.$item['prop1']);       // etc
    }
}

如果文件很大,由于内存限制,此工作流程不再起作用。您可以使用fopen() / fgets() / fclose()一次阅读一行并处理它:

$fh = fopen($logpath, 'r');
while (! feof($fh)) {
    $line = fgets($fh);
    $entry = json_decode($line, TRUE);
    foreach ($entry as $item) {
        echo('IP: '.$item['ip'].'; prop1: '.$item['prop1']);       // etc
    }
}
fclose($fh);

但是如果不满足每行一个有效JSON的假设,则上述代码片段都不起作用。在这种情况下,您必须自己实现一个JSON解析器(或找到一个已经实现的解析器),它能够从输入字符串中读取所需数量的数据,直到找到完整的JSON字符串。

<强>更新

您在评论中说该文件每行不包含一个JSON。这使得上面的代码无用。但是,如果文件不大并且其整个内容可以加载到内存中,那就有希望了。您可以尝试在内存中加载文件的内容,尝试修补它以将其转换为有效的JSON,然后对其进行解码。

如果文件中的所有JSON看起来都与您在问题中发布的JSON(即对象数组)有关,则可以尝试识别字符序列][(或{{ 1}}和}])仅由空格字符分隔。这是JSON结束([{)而下一个开始(}])的地方。如果在每对[{]之间插入逗号并将所有内容包装在[[中,则结果应为有效的JSON,在解码时生成数组。数组的每个元素都是用于从输入文件生成每个JSON的数组。

让我们尝试编写代码:

]

正则表达式

用于标识原始JSON边界的正则表达式,分为几部分:

// Get the entire content of the log file in memory in $text
$text  = file_get_contents($logpath);
// Try to patch the content of the file to generate a larger JSON
$fixed = '['.preg_replace('/]\s*\[/', '],[', $text).']';
// Decode the JSON to arrays
$all   = json_decode($fixed, TRUE);

// If $all is not FALSE then we did it!
foreach ($all as $entry) {
    // $entry is one entry from the original log
    // it used to be an array of objects on the source
    // but we decoded the objects to associative arrays
    foreach ($entry as $item) {
        echo('IP: '.$item['ip'].'; prop1: '.$item['prop1']);       // etc
    }
}

答案 2 :(得分:-1)

首先,你的json有问题。 最后一个值需要包含在“。 你有“xxx [xxx]}的地方,你应该有”xxx [xxx]“}并且结束”。

之后,只需将字符串传递给json_decode()函数。

答案 3 :(得分:-1)

$a = [{"ip":"XXX","prop1":"d","prop2":"xxx","prop3":{"index":0,"type":"xxx"},"id":"xxxxx","reason": "xxx [xxx]"}]

[{&#34; IP&#34;:&#34; XXX&#34;&#34; PROP1&#34;:&#34; d&#34;&#34; PROP2&#34 ;: &#34; XXX&#34;&#34; prop3&#34; {&#34;指数&#34;:0,&#34;类型&#34;:&#34; XXX&#34;},& #34; id&#34;:&#34; xxxxx&#34;,&#34;原因&#34;:&#34; xxx [xxx]&#34;},  {&#34; IP&#34;:&#34; XXX&#34;&#34; PROP1&#34;:&#34; d&#34;&#34; PROP2&#34;:&#34; XXX&#34;&#34; prop3&#34; {&#34;指数&#34;:0,&#34;类型&#34;:&#34; XXX&#34;}&#34; ID& #34;:&#34; xxxxx&#34;,&#34;原因&#34;:&#34; xxx [xxx]&#34;}]

$j = json_decode($a,true);
array_walk_recursive($j,"decode");