標準 JSON 規範要求鍵名必須用雙引號包裹({"name":"value"}),但實務上常遇到類 JavaScript 物件字面值格式({name:"value"}),導致 json_decode 回傳 NULL。本文提供正則預處理方案,相容解析此類非標準 JSON。
<?php
$standard = '{"name":"fdipzone"}';
$nonStandard = '{name:"fdipzone"}';
var_dump(json_decode($standard, true)); // 正常解析
var_dump(json_decode($nonStandard, true)); // NULL
?>
ext_json_decode()<?php
/**
* 相容鍵名無雙引號的 JSON 解析
* @param string $str JSON 字串
* @param bool $assoc true 回傳陣列,false 回傳物件
* @return array|object|null
*/
function ext_json_decode($str, $assoc = false) {
// 偵測是否有「單字:」模式(鍵名無引號)
if (preg_match('/\w:/', $str)) {
// 將 key: 替換為 "key":
$str = preg_replace('/(\w+):/is', '"$1":', $str);
}
return json_decode($str, $assoc);
}
// 測試
$standard = '{"name":"fdipzone"}';
$nonStandard = '{name:"fdipzone"}';
var_dump(ext_json_decode($standard, true)); // 正常
var_dump(ext_json_decode($nonStandard, true)); // 也能正常解析!
?>
/\w:/:偵測「單字字元後接冒號」,粗略判斷是否為無引號鍵名/(\w+):/is:捕獲鍵名(字母數字底線),替換為 "$1":i 忽略大小寫,s 讓 . 匹配換行(雖此處未用到)composer require colinodell/json5)。\w 不匹配純數字鍵名(如 {123:"val"}),若需支援請調整正則為 /([\w\d]+):/。// 使用 JSON5 解析器(支援註解、尾隨逗號、無引號鍵名等)
// composer require colinodell/json5
use ColinODell\Json5\Json5;
$data = Json5::decode('{name:"fdipzone", age: 25,}'); // 完美解析
$json = '{"desc":"He said \"Hello\""}';
// PHP 中字串本身需跳脫,json_decode 可正確處理標準 JSON
// 若為非標準且值含引號,建議先修正為標準 JSON 再解析