我有一个日志文件,看起来像这样:
[{"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个日志项。
答案 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");