示例代码:
<?php
$json = "['foo', 'bar']";
var_dump( json_decode($json) );
适用于 PHP 5.5.3 ,但对于较低版本的PHP版本无效
它可以在我的机器上使用PHP 5.5.3,但在其他任何地方都失败了。
我知道这是不正确的JSON,但我的网络服务为我提供了带有'
符号的JSON以及"
['foo', "bar", {'test': "crazy \"markup\""}]
如何在PHP 5.3中使用撇号解析JSON数据? 显然我想要解析的原始JSON更复杂。
(我无法在生产服务器上升级我的PHP,也无法从webservice获取正确的JSON)
答案 0 :(得分:32)
以下是此问题的替代解决方案:
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的版本似乎进入无限循环。测试:
$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
)
)
答案 1 :(得分:6)
这是一个简单的解析器,可以为您修复报价。如果它遇到不在双引号'
中的"
引用,它将假定它是错误的并替换该引号内的双引号,并将引号括起来用双引号:
示例强>:
<?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
)
)
答案 2 :(得分:4)
一种解决方案是使用NodeJS构建代理。 NodeJS会正常处理有问题的JSON并返回一个干净的版本:
johan:~ # node
> JSON.stringify(['foo', 'bar']);
'["foo","bar"]'
也许编写一个简单的Node脚本,将JSON数据作为STDIN接受,并将经过验证的JSON返回给STDOUT。这样你可以用PHP调用它。
缺点是您的服务器需要NodeJS。不确定这对你来说是否有问题。
答案 3 :(得分:3)
NikiCs´ answer已经出现了。您的输入似乎是手动生成的,因此完全有可能在'
单引号字符串中,您会收到不带引号的"
双打。因此,建议使用正则表达式assertion,而不是简单的搜索和替换。
但是也有一些userland JSON解析器支持更多的Javascript表达式语法。此时最好谈论 JSOL ,JavaScript Object Literals。
Services_JSON可以解码:
不需要其他选项,只需= (new Services_JSON)->decode($jsol);
这实际上意味着没有JSON扩展的早期PHP版本的后备。它重新实现了PHP upgradephp。但是还有upgrade.php.prefixed
版本,你可以在这里使用。
它引入了另一个标志JSON_PARSE_JAVASCRIPT
。
up_json_decode($jsol, false, 512, JSON_PARSE_JAVASCRIPT);
我完全忘记在文档中提及这一点,但它也支持单引号字符串 例如:
{ num: 123, "key": "value", 'single': 'with \' and unquoted " dbls' }
将解码为:
stdClass Object
(
[num] => 123
[key] => value
[single] => with ' and unquoted " double quotes
)
json_decode()
JasonDecoder ArtisticPhoenix确实支持不带引号的键和文字,但没有'
- 引用字符串。然而,它很容易理解或扩展。
显然,userland中的任何JSOL tokenizer / parser都比预处理格式错误的JSON慢得多。如果您不希望从您的网络服务中获得进一步的问题,请转而使用正则表达式/报价转换。
答案 4 :(得分:2)
如果您知道PHP 5.5。+将优雅地解析此JSON,我会通过PHP5.5 + Web服务器上的代理脚本管理Web服务响应,该服务器会对较低版本的响应进行清理 - 这意味着{{1 }};这是一种稳定可靠的方法。
如果您通过配置值配置Web服务URL,则可以通过访问代理来使用较低版本,通过直接访问Web服务获得更高版本。
答案 5 :(得分:0)
您可以使用(并可能修改/扩展)库来从提供的JSON构建AST,并用双引号替换单引号。
https://github.com/Seldaek/jsonlint/blob/master/src/Seld/JsonLint/Lexer.php
可能是一个好的开始。
答案 6 :(得分:0)
快速解决方案可能是str_replace("'","\"",$string)
。这取决于很多事情,但我认为你可以尝试一下。