Menu

Hàm json_decode() trong PHP: chuyển JSON thành mảng

json_decode($json, true) chuyển một chuỗi JSON thành mảng kết hợp trong PHP; không có true thì bạn nhận được đối tượng stdClass. Tìm hiểu giá trị lồng nhau, xử lý lỗi với JSON_THROW_ON_ERROR, json_validate() và lý do json_decode trả về null.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

json_decode($json, true) chuyển một chuỗi JSON thành giá trị PHP, trong đó mọi đối tượng JSON trở thành mảng kết hợp. Bỏ true đi thì đối tượng JSON sẽ thành đối tượng stdClass, được đọc bằng ->. JSON không hợp lệ cho ra null.

Đầu ra:

Ada
js
Ada
php
Array
(
    [name] => Ada
    [age] => 36
    [langs] => Array
        (
            [0] => php
            [1] => js
        )

    [admin] => 1
)

Mảng JSON luôn trở thành list trong PHP, dù bạn chọn chế độ nào. Chiều ngược lại, từ PHP sang JSON, là json_encode().

Mảng kết hợp hay đối tượng: true và false

Cả hai chế độ chứa cùng một dữ liệu; hãy chọn cách đọc dễ hiểu hơn trong code của bạn. Mảng dùng được với mọi hàm mảng (array_column, array_map, isset($data['key'])), nên phần lớn code truyền true. Đối tượng cần cú pháp ngoặc nhọn cho những khóa không phải tên thuộc tính hợp lệ, như khóa có dấu gạch ngang hoặc khóa là số:

Đầu ra:

Ada zero London
Ada zero London
object(stdClass)#2 (1) {
  ["city"]=>
  string(6) "London"
}

Tham số thứ tư nhận các cờ. JSON_OBJECT_AS_ARRAY cũng cho ra mảng, nhưng chỉ khi đối số thứ hai là null (giá trị mặc định của nó): json_decode($json, flags: JSON_OBJECT_AS_ARRAY) trả về mảng, còn json_decode($json, false, 512, JSON_OBJECT_AS_ARRAY) vẫn trả về đối tượng.

Duyệt JSON lồng nhau

Response của API thường là một danh sách đối tượng nằm trong một đối tượng. Decode một lần, rồi duyệt bằng foreach, và dùng ?? cho những trường có thể bị thiếu:

Đầu ra:

#1 Ada <ada@example.com> roles: admin, editor
#2 Linus <no email> roles: none
#3 Grace <grace@example.com> roles: editor
Array
(
    [1] => Ada
    [2] => Linus
    [3] => Grace
)

Xử lý JSON không hợp lệ

json_decode() trả về null với JSON không hợp lệ, nhưng null cũng là kết quả đúng cho văn bản JSON null, nên chỉ riêng null không cho biết lệnh có thất bại hay không. json_last_error_msg() cho biết lý do của lần gọi gần nhất. Để tìm chỗ lỗi trong một tài liệu dài, hãy dán nó vào công cụ định dạng JSON, công cụ này chỉ ra dòng có lỗi. Cách gọn gàng hơn là JSON_THROW_ON_ERROR, cờ này ném ra một JsonException:

Đầu ra:

NULL
Syntax error
NULL
No error
Invalid JSON: Syntax error

Đối số thứ ba, 512, là độ sâu lồng nhau tối đa (giá trị mặc định). Với named argument, bạn có thể bỏ qua nó: json_decode($json, true, flags: JSON_THROW_ON_ERROR).

Kiểm tra chuỗi JSON hợp lệ với json_validate()

PHP 8.3 bổ sung json_validate(). Hàm trả lời true hoặc false mà không tạo ra các mảng đã decode, nên tốn ít bộ nhớ hơn decode khi bạn chỉ cần câu trả lời có hoặc không, ví dụ để từ chối sớm một request body:

Đầu ra:

'{"a": 1}'    valid
'[1, 2, 3]'   valid
'"text"'      valid
'{a: 1}'      invalid: Syntax error
'{\'a\': 1}'  invalid: Syntax error
''            invalid: Syntax error

Nếu đằng nào bạn cũng dùng dữ liệu, hãy bỏ qua json_validate() và decode với JSON_THROW_ON_ERROR: kiểm tra trước sẽ khiến chuỗi bị phân tích hai lần.

Đọc file JSON

Đọc file bằng file_get_contents() rồi decode chuỗi. Khối code này ghi settings.json trước để có file mà đọc:

Đầu ra:

Theme: dark
Plugins: 2
{
    "theme": "dark",
    "fontSize": 16,
    "plugins": [
        "git",
        "lint"
    ]
}

Vì sao json_decode trả về null: các nguyên nhân thường gặp

JSON chặt chẽ hơn cú pháp JavaScript và cú pháp mảng của PHP. Chuỗi nào bên dưới trông cũng có vẻ hợp lý, nhưng tất cả đều trả về null. Chạy để xem lý do của từng chuỗi, rồi sửa một chuỗi và chạy lại:

Đầu ra:

single quotes    Syntax error
unquoted key     Syntax error
trailing comma   Syntax error
comment          Syntax error
byte order mark  Syntax error
too deep         Maximum stack depth exceeded
float(1.2345678901234567E+19)
string(20) "12345678901234567890"

Byte order mark không hiện ra trong phần lớn trình soạn thảo và là lý do kinh điển khiến một file JSON "trông vẫn ổn" nhưng không decode được. Hãy loại bỏ nó bằng $text = preg_replace('/^\xEF\xBB\xBF/', '', $text); trước khi decode.

Câu hỏi thường gặp

Làm sao chuyển JSON thành mảng trong PHP?

Truyền true làm đối số thứ hai: json_decode('{"name":"Ada"}', true) trả về ['name' => 'Ada'], nên bạn đọc giá trị bằng $data['name']. Không có true, đối tượng JSON trở thành đối tượng stdClass và bạn viết $data->name.

Vì sao json_decode trả về null?

JSON không hợp lệ (dùng nháy đơn, thừa dấu phẩy ở cuối, khóa không nằm trong nháy kép, có byte order mark), lồng sâu hơn giới hạn độ sâu, hoặc JSON thật sự là null. Hãy xem json_last_error_msg(), hoặc decode với JSON_THROW_ON_ERROR để nhận một JsonException kèm lý do.

Làm sao kiểm tra một chuỗi có phải JSON hợp lệ trong PHP?

Từ PHP 8.3, json_validate($string) trả về true hoặc false mà không cần tạo ra giá trị đã decode. Với các phiên bản cũ hơn, hãy decode rồi kiểm tra json_last_error() === JSON_ERROR_NONE.

Làm sao đọc file JSON trong PHP?

Đọc file rồi decode nó: $data = json_decode(file_get_contents('data.json'), true, flags: JSON_THROW_ON_ERROR);. file_get_contents() trả về false nếu không tìm thấy file, nên hãy kiểm tra điều đó trước.

Làm sao truy cập khóa JSON có dấu gạch ngang trong PHP?

Decode thành mảng rồi dùng $data['first-name'], hoặc với đối tượng thì dùng dấu ngoặc nhọn: $obj->{'first-name'}. Cú pháp ngoặc nhọn này cũng dùng được cho khóa là số, như $obj->{'0'}.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu