由于昨天我试图解决这个棘手的问题,经过大量的头发拉动,我想出了这个解决方案。
首先让我们澄清我们的假设。
- json字符串应该是正确的格式。
- 键和值用双引号引起来。
分析问题:
我们知道格式化像这样的JSON键( “KeyString中” :)和JSON值( “的valueString”)
KeyString中:是除“(:”)以外的任何字符序列。
valueString:是除((,))以外的任何字符序列。
我们的目标是在valueString之内转义报价,以达到我们需要分开keyStrings和valueStrings。
- 但我们也有这样的有效的JSON格式(“KeyString中”:数字),这将导致一个问题,因为它打破了假设说值总是以结束(”)
- 另一个问题是具有类似于空值( “KeyString中”: “ ”)
现在分析这个问题后,我们可以说
- KeyString中JSON有(“)之前和(” :)后。
- JSON的valueString可以具有(: “)之前和(”)OR (:)之前,然后作为数字值(,)后OR (:),接着(”“),则后(,)
解决办法: 使用这个事实的代码将
function escapeJsonValues($json_str){
$patern = '~(?:,\s*"((?:.(?!"\s*:))+.)"\s*(?=\:))(?:\:\s*(?:(\d+)|("\s*")|(?:"((?!\s*")(?:.(?!"\s*,))+.)")))~';
//remove { }
$json_str = rtrim(trim(trim($json_str),'{'),'}');
if(strlen($json_str)<5) {
//not valid json string;
return null;
}
//put , at the start nad the end of the string
$json_str = ($json_str[strlen($json_str)-1] ===',') ?','.$json_str :','.$json_str.',';
//strip all new lines from the string
$json_str=preg_replace('~[\r\n\t]~','',$json_str);
preg_match_all($patern, $json_str, $matches);
$json='{';
for($i=0;$i<count($matches[0]);$i++){
$json.='"'.$matches[1][$i].'":';
//value is digit
if(strlen($matches[2][$i])>0){
$json.=$matches[2][$i].',';
}
//no value
elseif (strlen($matches[3][$i])>0) {
$json.='"",';
}
//text, and now we can see if there is quotations it will be related to the text not json
//so we can add slashes safely
//also foreword slashes should be escaped
else{
$json.='"'.str_replace(['\\','"' ],['/','\"'],$matches[4][$i]).'",';
}
}
return trim(rtrim($json,','),',').'}';
}
注:代码实现了空白。
如果你有可能做到这一点,你应该以正确的方式将它转义出来 – ThomasP1988
如果API返回'{“key”:“foo”,“bar”:“baz”}''。是否应该转换为'{“key”:“foo”,“bar”:“baz”}(其中有两个键:'key'和'bar',值为'foo'和'baz' ),还是应该将其转换为“{”key“:”foo \“,\”bar \“:\”baz“}(1个键,'key',一个值)?目前还不清楚你想如何改变这种状况。 – Cornstalks
我无法更改api,因为它不是我的。请帮我解决转义字符串的问题。 – SohrabZ