如何使用撇号而不是引号json_decode无效的 JSON

2022-08-30 16:32:18

示例代码:

<?php

$json = "['foo', 'bar']";

var_dump( json_decode($json) );

它适用于PHP 5.5.3,但对于较低的PHP版本,它失败了。

它适用于我的机器与PHP 5.5.3,但它在其他地方都失败了。

我知道这是不正确的JSON,但我的Web服务给我的JSON带有符号'"

['foo', "bar", {'test': "crazy \"markup\""}]

沙盒

如何在PHP 5.3中解析带有撇号的JSON数据?显然,我想解析的原始JSON更复杂。

(我无法在生产服务器上升级我的PHP,也无法从Webservice获得正确的JSON)


答案 1

以下是此问题的替代解决方案:

function fixJSON($json) {
    $regex = <<<'REGEX'
~
    "[^"\\]*(?:\\.|[^"\\]*)*"
    (*SKIP)(*F)
  | '([^'\\]*(?:\\.|[^'\\]*)*)'
~x
REGEX;

    return preg_replace_callback($regex, function($matches) {
        return '"' . preg_replace('~\\\\.(*SKIP)(*F)|"~', '\\"', $matches[1]) . '"';
    }, $json);
}

这种方法在两个方面比h2ooooooo的功能更健壮:

  • 它通过对双引号字符串应用额外的转义来保留单引号字符串中出现的双引号。h2o的变体将用双引号代替它们,从而更改字符串的值。
  • 它将正确处理转义的双引号,为此h2o的版本似乎进入了无限循环。\"

测试:

$brokenJSON = <<<'JSON'
['foo', {"bar": "hel'lo", "foo": 'ba"r ba\"z', "baz": "wor\"ld ' test"}]
JSON;

$fixedJSON = fixJSON($brokenJSON);
$decoded = json_decode($fixedJSON);

var_dump($fixedJSON);
print_r($decoded);

输出:

string(74) "["foo", {"bar": "hel'lo", "foo": "ba\"r ba\"z", "baz": "wor\"ld ' test"}]"
Array
(
    [0] => foo
    [1] => stdClass Object
        (
            [bar] => hel'lo
            [foo] => ba"r ba"z
            [baz] => wor"ld ' test
        )
)

答案 2

这是一个简单的解析器,它将为您修复报价。如果它遇到一个不在双引号中的引号,它将假设它是错误的,并替换该引号内的双引号,并将引号括起来为双引号:'"

示例

<?php
    function fixJSON($json) {
        $newJSON = '';

        $jsonLength = strlen($json);
        for ($i = 0; $i < $jsonLength; $i++) {
            if ($json[$i] == '"' || $json[$i] == "'") {
                $nextQuote = strpos($json, $json[$i], $i + 1);
                $quoteContent = substr($json, $i + 1, $nextQuote - $i - 1);
                $newJSON .= '"' . str_replace('"', "'", $quoteContent) . '"';
                $i = $nextQuote;
            } else {
                $newJSON .= $json[$i];
            }
        }

        return $newJSON;
    }

    $brokenJSON = "['foo', {\"bar\": \"hel'lo\", \"foo\": 'ba\"r'}]";
    $fixedJSON = fixJSON( $brokenJSON );

    var_dump($fixedJSON);

    print_r( json_decode( $fixedJSON ) );
?>

输出

string(41) "["foo", {"bar": "hel'lo", "foo": "ba'r"}]"
Array
(
    [0] => foo
    [1] => stdClass Object
        (
            [bar] => hel'lo
            [foo] => ba'r
        )

)

演示


推荐