解碼 JSON 字串

所述 json_decode() 函式採用一個 JSON 編碼的字串的第一個引數並將其解析為一個 PHP 變數。

通常,如果 JSON 物件中的頂級項是字典,則 json_decode() 將返回 \ stdClass物件, 如果 JSON 物件是陣列,則返回索引陣列。對於某些標量值,它還會返回標量值或 NULL,例如簡單字串,truefalsenull。它還會在任何錯誤時返回 NULL

// Returns an object (The top level item in the JSON string is a JSON dictionary)
$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$object = json_decode($json_string);
printf('Hello %s, You are %s years old.', $object->name, $object->age);
#> Hello Jeff, You are 20 years old.

// Returns an array (The top level item in the JSON string is a JSON array)
$json_string = '["Jeff", 20, true, ["red", "blue"]]';
$array = json_decode($json_string);
printf('Hello %s, You are %s years old.', $array[0], $array[1]);

使用 var_dump() 檢視上面解碼的物件上每個屬性的型別和值。

// Dump our above $object to view how it was decoded
var_dump($object);

輸出(注意變數型別):

class stdClass#2 (4) {
 ["name"] => string(4) "Jeff"
 ["age"] => int(20)
 ["active"] => bool(true)
 ["colors"] =>
   array(2) {
     [0] => string(3) "red"
     [1] => string(4) "blue"
   }
}

注意: JSON 中的變數型別已轉換為其 PHP 等效項。

要返回 JSON 物件的關聯陣列而不是返回物件,請將 true 作為第二個引數傳遞給 json_decode()

$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$array = json_decode($json_string, true); // Note the second parameter
var_dump($array);

輸出(注意陣列關聯結構):

array(4) {
  ["name"] => string(4) "Jeff"
  ["age"] => int(20)
  ["active"] => bool(true)
  ["colors"] =>
  array(2) {
    [0] => string(3) "red"
    [1] => string(4) "blue"
  }
}

如果要返回的變數不是物件,則第二個引數($assoc)無效。

注意: 如果使用 $assoc 引數,則會丟失空陣列和空物件之間的區別。這意味著再次在解碼輸出上執行 json_encode() 將導致不同的 JSON 結構。

如果 JSON 字串在遞迴時具有超過 512 個元素的深度早於 5.2.3 的版本中的 20 個元素,或版本 5.2.3 中的 128 個元素 ),則函式 json_decode() 將返回 NULL。在版本 5.3 或更高版本中,可以使用第三個引數($depth)來控制此限制,如下所述。

根據手冊:

PHP 實現了原始 »RFC 4627 中指定的 JSON 超集 - 它還將編碼和解碼標量型別和 NULL。RFC 4627 僅在巢狀在陣列或物件中時才支援這些值。雖然這個超集與更新的 »RFC 7159 (旨在取代 RFC 4627)和 »ECMA-404 中的“JSON 文字”的擴充套件定義一致,但這可能會導致與舊的 JSON 解析器的互操作性問題,這些解析器嚴格遵守 RFC 4627 編碼單個標量值。

這意味著,例如,一個簡單的字串將被視為 PHP 中的有效 JSON 物件:

$json = json_decode('"some string"', true);
var_dump($json, json_last_error_msg());

輸出:

string(11) "some string"
string(8) "No error"

但是簡單的字串,不在陣列或物件中,不屬於 RFC 4627 標準。因此,像 JSLintJSON Formatter&Validator (在 RFC 4627 模式下) 這樣的線上檢查會給你一個錯誤。

遞迴深度有第三個 $depth 引數(預設值為 512),這意味著要解碼的原始物件內的巢狀物件的數量。

第四個 $options 引數。它目前只接受一個值 JSON_BIGINT_AS_STRING。預設行為(不包括此選項)是將大整數轉換為浮點數而不是字串。

無效的 true,false 和 null 文字的非小寫變體不再被接受為有效輸入。

所以這個例子:

var_dump(json_decode('tRue'), json_last_error_msg());
var_dump(json_decode('tRUe'), json_last_error_msg());
var_dump(json_decode('tRUE'), json_last_error_msg());
var_dump(json_decode('TRUe'), json_last_error_msg());
var_dump(json_decode('TRUE'), json_last_error_msg());
var_dump(json_decode('true'), json_last_error_msg());

在 PHP 5.6 之前:

bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"

之後:

NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
bool(true)
string(8) "No error"

falsenull 也出現類似的行為。

請注意,如果無法轉換字串,json_decode() 將返回 NULL

$json = "{'name': 'Jeff', 'age': 20 }" ;  // invalid json 

$person = json_decode($json);
echo $person->name;    //  Notice: Trying to get property of non-object: returns null
echo json_last_error();     
#  4 (JSON_ERROR_SYNTAX)
echo json_last_error_msg(); 
#  unexpected character 

僅依靠返回值 NULL 來檢測錯誤是不安全的。例如,如果 JSON 字串只包含 null,則 json_decode() 將返回 null,即使沒有發生錯誤。