php json字串解析中的引號問題
阿新 • • 發佈:2020-08-16
背景
json字串的解析非常常見,但是php中單雙引號含義不同以及各種字串處理函式對json字串的處理常常會導致json_decode()
函式解析失敗。這裡藉著工作中遇到的一個問題整理一下相關的知識點,做個沉澱。
php中的單雙引號
區別
單引號中的內容會被認為就是純文字。雙引號中的內容則會經過解析,其中的變數、斜槓轉義符等會被處理為對應的值。
關於用法
在php以前的版本中使用單引號處理速度比使用雙引號速度要快,但是php7以後兩者已經沒有區別。對於需要進行變數替換的字串只能使用雙引號,對於純字串鳥哥在文章中還是建議大家使用雙引號,理由是C/C++中雙引號表示字串以及HTML中屬性值需要使用雙引號包裹,與別的語言習慣保持一致。
問題說明
解析一個前端通過post form表單提交過來的json字串,但是一直報json_decode()
返回NULL,呼叫ljson_last_error()
返回4,呼叫json_last_error_msg()
返回Syntax error,但是json字串能夠被線上的json解析器正確處理。
排查
前端輸入的字串如下
[{"name":"測試新增車主","mobile":"13322232214"},{"name":"測試新增車主2","mobile":"13322232215"}]
將接收到的字串使用var_dump()
打印出來
string '[{\"name\":\"測試新增車主\",\"mobile\":\"13322232214\"},{\"name\":\"測試新增車主2\",\"mobile\":\"13322232215\"}]' (length=124)
打印出的字串是單引號包含並且內部包含了轉義字串\"
將字串複製出來,使用雙引號包裹在進行解析
<?php $str = "[{\"name\":\"測試新增車主\",\"mobile\":\"13322232214\"},{\"name\":\"測試新增車主2\",\"mobile\":\"13322232215\"}]"; var_dump($str); $array = json_decode($str, true); var_dump($array); var_dump(json_last_error()); var_dump(json_last_error_msg());
測試結果如下
PS D:\php\WWW> php .\test.php
string(108) "[{"name":"測試新增車主","mobile":"13322232214"},{"name":"測試新增車主2","mobile":"13322232215"}]"
array(2) {
[0]=>
array(2) {
["name"]=>
string(18) "測試新增車主"
["mobile"]=>
string(11) "13322232214"
}
[1]=>
array(2) {
["name"]=>
string(19) "測試新增車主2"
["mobile"]=>
string(11) "13322232215"
}
}
int(0)
string(8) "No error"
這裡可以觀察到打印出來的json字串被雙引號包裹,並且字串內部的轉義字元\"
已經被處理為"
,json_decode()
函式也可以正確解析該json。因此這裡可以確定問題就是接收到字串內部含有轉義字元\"
但是外部不是使用雙引號包裹的。
解決
追了一下原始碼發現由於安全原因所有的輸入都經過addslashes()
函式處理防止sql注入,這裡使用stripcslashes()
函式去掉json字串中的反斜槓就解決了該問題。
總結php json_encode喊出解析json字串中的引號問題
- 內層的索引和值必須是雙引號
- 外層是單引號時,內層的雙引號不需要轉義(不能是
\"
,必須是"
) - 外層是雙引號時,內層的雙引號需要轉義(不能是
"
,必須是\"
)