PHP:如何从字符串转储中提取JSON字符串

时间:2013-10-06 15:48:12

标签: php regex json string

我有一个巨大的字符串转储,其中包含常规文本和JSON的混合。我想从字符串转储中分离/删除JSON对象并仅获取文本。

以下是一个例子:

This is some text {'JSON':'Object'} Here's some more text {'JSON':'Object'} Yet more text {'JSON':'Object'} Again, some text.

我的目标是获得一个看起来像这样的文本转储(基本上是删除了JSON):

This is some text Here's some more text Yet more text Again, some text.

我需要在PHP中完成所有这些操作。文本转储始终是随机的,JSON数据结构也是随机的(大部分都是深度嵌套的)。转储可能会也可能不会以JSON开头,它可能包含也可能不包含字符串转储中的多个JSON对象。

我尝试在字符串上使用json_decode但结果最终为NULL

编辑:Amal的答案非常接近我想要的(见下面的第2条评论):

$str = preg_replace('#\{.*?\}#s', '', $str);

然而,它根本没有摆脱嵌套对象;例如括号中包含的数据:[][{}]

抱歉,我不是正则表达式的专家。

我意识到你们中的一些人可能需要一个我正在处理的字符串转储的更具体的例子;因此我创建了一个要点(请注意,这不是静态数据;转储中的数据将始终不同;上面的示例只是简化了我正在使用的字符串):https://gist.github.com/anonymous/6855800

3 个答案:

答案 0 :(得分:8)

我希望您使用JSON_decode发布您在尝试时使用的代码,但是很好......

您可以在PHP中使用递归正则表达式嵌套大括号:

$res = preg_replace('~\{(?:[^{}]|(?R))*\}~', '', $text);

regex101 demo(以蓝色突出显示的部分将被删除)。

答案 1 :(得分:1)

获取一个堆栈并开始从开头迭代字符串。

for($i=0;i<count($str);$i++){
}

当你发现$str[i] == '{'将此元素推入堆栈并将start变量初始化为$i时:

$start = $i;

现在当字符串中出现{[时,开始进入堆栈。 如果发生]}并且堆栈顶部不是{],则表示这不是正确的json。 如果不是这样,那么弹出堆栈顶部并继续这样做直到堆栈为空。

此时你得到$end = $i;

这将是json字符串之一。 (从$start$end) 将此字符串推入另一个保留所有jsons的数组。

并继续处理直到你到达终点

答案 2 :(得分:0)

这是一个基于animesh seth答案的工作代码段。

if (strpos($msg, '{') !== false) {
    $msg = str_split($msg);
    // extract the json message.
    $json = '';
    $in = 0;
    foreach ($msg as $i => $char) {
        if ($char == '{') {
            $in++;
        }
        if ($in) {
            $json .= $msg[$i];
        }
        if ($char == '}') {
            $in--;
        }
    }
    if ($json) {
        $json = json_decode($json);
    }
    // do something with the json object.
}