2024 日本 PHP 研討會

json_decode

(PHP 5 >= 5.2.0, PHP 7, PHP 8, PECL json >= 1.2.0)

json_decode解碼 JSON 字串

說明

json_decode(
    字串 $json,
    ?bool $associative = null,
    int $depth = 512,
    int $flags = 0
): mixed

將 JSON 編碼的字串轉換為 PHP 值。

參數

json

要解碼的 json 字串

此函式僅適用於 UTF-8 編碼的字串。

注意:

PHP 實作了原始 » RFC 7159 中指定的 JSON 的超集。

associative

當設為 true 時,JSON 物件將會以關聯式 陣列 返回;當設為 false 時,JSON 物件將會以 物件 返回。當設為 null 時,JSON 物件將會以關聯式 陣列物件 返回,取決於 flags 中是否設定了 JSON_OBJECT_AS_ARRAY

depth

要解碼的結構的最大嵌套深度。該值必須大於 0,且小於或等於 2147483647

flags

JSON_BIGINT_AS_STRINGJSON_INVALID_UTF8_IGNOREJSON_INVALID_UTF8_SUBSTITUTEJSON_OBJECT_AS_ARRAYJSON_THROW_ON_ERROR 的位元遮罩。這些常數的行為在 JSON 常數 頁面上有描述。

回傳值

以適當的 PHP 類型返回 json 中編碼的值。未加引號的值 truefalsenull 分別返回 truefalsenull。如果 json 無法解碼或編碼數據的嵌套深度超過限制,則返回 null

錯誤/例外

如果 depth 超出允許範圍,則從 PHP 8.0.0 開始會拋出 ValueError,而在此之前,會引發層級為 E_WARNING 的錯誤。

更新日誌

版本 說明
7.3.0 新增了 JSON_THROW_ON_ERROR flags
7.2.0 associative 現在可以為 null。
7.2.0 新增了 JSON_INVALID_UTF8_IGNOREJSON_INVALID_UTF8_SUBSTITUTE flags
7.1.0 空的 JSON 鍵 ("") 可以編碼為空的物件屬性,而不是使用值為 _empty_ 的鍵。

範例

範例 #1 json_decode() 範例

<?php
$json
= '{"a":1,"b":2,"c":3,"d":4,"e":5}';

var_dump(json_decode($json));
var_dump(json_decode($json, true));

?>

上述範例會輸出:

object(stdClass)#1 (5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

array(5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}

範例 #2 存取無效的物件屬性

若要存取物件中包含 PHP 命名慣例不允許的字元(例如連字號)的元素,可以將元素名稱用大括號和單引號括起來。

<?php

$json
= '{"foo-bar": 12345}';

$obj = json_decode($json);
print
$obj->{'foo-bar'}; // 12345

?>

範例 #3 使用 json_decode() 的常見錯誤

<?php

// 以下字串是有效的 JavaScript,但不是有效的 JSON

// 名稱和值必須用雙引號括起來
// 單引號無效
$bad_json = "{ 'bar': 'baz' }";
json_decode($bad_json); // null

// 名稱必須用雙引號括起來
$bad_json = '{ bar: "baz" }';
json_decode($bad_json); // null

// 不允許尾隨逗號
$bad_json = '{ bar: "baz", }';
json_decode($bad_json); // null

?>

範例 #4 depth 錯誤

<?php
// 將一些資料編碼,最大深度為 4(陣列 -> 陣列 -> 陣列 -> 字串)
$json = json_encode(
array(
1 => array(
'English' => array(
'One',
'January'
),
'French' => array(
'Une',
'Janvier'
)
)
)
);

// 顯示不同深度的錯誤。
var_dump(json_decode($json, true, 4));
echo
'最後一個錯誤:', json_last_error_msg(), PHP_EOL, PHP_EOL;

var_dump(json_decode($json, true, 3));
echo
'最後一個錯誤:', json_last_error_msg(), PHP_EOL, PHP_EOL;
?>

上述範例會輸出:

array(1) {
  [1]=>
  array(2) {
    ["English"]=>
    array(2) {
      [0]=>
      string(3) "One"
      [1]=>
      string(7) "January"
    }
    ["French"]=>
    array(2) {
      [0]=>
      string(3) "Une"
      [1]=>
      string(7) "Janvier"
    }
  }
}
Last error: No error

NULL
Last error: Maximum stack depth exceeded

範例 #5 使用 json_decode() 處理大整數

<?php
$json
= '{"number": 12345678901234567890}';

var_dump(json_decode($json));
var_dump(json_decode($json, false, 512, JSON_BIGINT_AS_STRING));

?>

上述範例會輸出:

object(stdClass)#1 (1) {
  ["number"]=>
  float(1.2345678901235E+19)
}
object(stdClass)#1 (1) {
  ["number"]=>
  string(20) "12345678901234567890"
}

注意事項

注意:

JSON 規格並非 JavaScript,而是 JavaScript 的子集。

注意:

如果解碼失敗,可以使用 json_last_error() 來判斷錯誤的確切性質。

另請參考

新增註解

使用者貢獻的註解 5 則註解

Lennart Hengstmengel
2 年前
可以使用 $associative = true 選項將 JSON 解碼為 PHP 陣列。需要注意的是,PHP 中的關聯陣列在與 JSON 轉換時,可以是「列表」或「物件」,取決於鍵值(或缺少鍵值)。

你可能會認為重新編碼和解碼 JSON 字串會永遠產生相同的結果,但請參考以下範例:

$json = '{"0": "No", "1": "Yes"}';
$array = json_decode($json, true); // 解碼為關聯式雜湊陣列
print json_encode($array) . PHP_EOL;

這將會輸出與原始字串不同的 JSON 字串

["No","Yes"]

物件已經變成陣列了!

同樣地,一個沒有連續以零為基底數值索引的陣列,在編碼成 JSON 時會變成物件而不是列表。

$array = [
'first',
'second',
'third',
];
print json_encode($array) . PHP_EOL;
// 移除第二個元素
unset($array[1]);
print json_encode($array) . PHP_EOL;

輸出結果會是

["first","second","third"]
{"0":"first","2":"third"}

陣列已經變成物件了!

換句話說,從 PHP 陣列解碼/編碼成 JSON 並非總是對稱的,或者可能不會總是返回你預期的結果!

另一方面,使用 stdClass 物件(預設)進行解碼/編碼則始終是對稱的。

陣列可能比物件更容易操作/轉換。但特別是當你需要解碼和重新編碼 JSON 時,謹慎的做法是解碼成物件而不是陣列。

如果你要強制將陣列編碼成 JSON 列表(所有陣列鍵值將被捨棄),請使用

json_encode(array_values($array));

如果你要強制將陣列編碼成 JSON 物件,請使用

json_encode((object)$array);

另請參閱:https://php.dev.org.tw/manual/en/function.array-is-list.php
cubefox at web dot NOSPAMPLEASE dot de
4 年前
警告:如同「返回值」章節所述,返回值 NULL 是模稜兩可的。它可以代表三種情況:

* 輸入字串的值為 "null"
* 解析輸入資料時發生錯誤
* 編碼資料的深度超過遞迴限制

要區分這些情況,可以使用 json_last_error()。
greaties at ghvernuft dot nl
1 年前
要載入 JSON 格式資料到物件中
(修正了我之前的留言中的錯誤)

<?php
function loadJSON($Obj, $json)
{
$dcod = json_decode($json);
$prop = get_object_vars ( $dcod );
foreach(
$prop as $key => $lock)
{
if(
property_exists ( $Obj , $key ))
{
if(
is_object($dcod->$key))
{
loadJSON($Obj->$key, json_encode($dcod->$key));
}
else
{
$Obj->$key = $dcod->$key;
}
}
}
return
$Obj;
}
?>

經測試

<?php
類別 Name
{
公用
$first;
公用
$last;
公用 函式
fullname()
{
回傳
$this->first . " " . $this->last;
}
}
$json = '{"first":"John","last":"Smith"}';

$infull = loadJSON((new Name), $json);
顯示
$infull->fullname();
Alien426
3 年前
瀏覽器不會被*開頭*為 BigInt (64 位元) 的整數噎住,而是在那之前 (53 位元) 的整數才會。當 JSON 處理函式不支援 BigInt 時,在現代瀏覽器中引入 BigInt 並沒有太大幫助。所以我正試圖彌補這個問題。我的方法是在將解碼後的陣列重新編碼為字串之前先處理它。
<?php
函式 fix_large_int(&$value)
{
若 (
is_int($value) && $value > 9007199254740991)
$value = strval($value);
}
$json_str = '{"id":[1234567890123456789,12345678901234567890]}';
$json_arr = json_decode($json_str, flags: JSON_BIGINT_AS_STRING | JSON_OBJECT_AS_ARRAY);
顯示(
json_encode($json_arr)); // {"id":[1234567890123456789,"12345678901234567890"]} (BigInt 已經在此處轉換為字串)
array_walk_recursive($json_arr, 'fix_large_int');
顯示(
json_encode($json_arr)); // {"id":["1234567890123456789","12345678901234567890"]}
?>
pablo dot pazos at cabolabs dot com
22 天前
回傳值說明「以適當的 PHP 類型回傳以 json 編碼的值。」,這似乎是 json_encode 的描述。
To Top