1. 程式人生 > 實用技巧 >php json字串解析中的引號問題

php json字串解析中的引號問題

背景

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字串中的引號問題

  1. 內層的索引和值必須是雙引號
  2. 外層是單引號時,內層的雙引號不需要轉義(不能是\",必須是"
  3. 外層是雙引號時,內層的雙引號需要轉義(不能是",必須是\"

參考文章