Menu

json_encode() trong PHP: chuyển mảng và đối tượng sang JSON

json_encode($value) chuyển một mảng, đối tượng hoặc giá trị vô hướng của PHP thành chuỗi JSON. Mảng kết hợp thành object JSON, danh sách thành mảng JSON, còn các flag như JSON_PRETTY_PRINT và JSON_UNESCAPED_UNICODE điều chỉnh đầu ra.

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_encode($value) trả về văn bản JSON cho một giá trị PHP. Mảng kết hợp (associative array) thành object JSON, danh sách (khóa 0, 1, 2...) thành mảng JSON, còn chuỗi, số, true, false và null thành giá trị tương ứng trong JSON.

Đầu ra:

{"name":"Ada","age":36,"langs":["php","js"],"admin":true,"manager":null}
string

Kết quả là một chuỗi bình thường, sẵn sàng gửi cho trình duyệt, lưu vào tệp hay một cột cơ sở dữ liệu, hoặc chuyển cho chương trình khác. Để chuyển JSON ngược lại thành PHP, dùng json_decode().

In JSON dễ đọc (pretty print)

json_encode() nhận các flag ở tham số thứ hai. JSON_PRETTY_PRINT thêm xuống dòng và thụt lề 4 dấu cách, đúng thứ bạn cần trong tệp cấu hình hay log gỡ lỗi. Kết hợp nhiều flag bằng |:

Đầu ra:

{
    "app": "shop",
    "debug": false,
    "db": {
        "host": "localhost",
        "port": 3306
    },
    "tags": []
}

Giữ chữ tiếng Nhật và văn bản UTF-8 khác dễ đọc

Mặc định json_encode() viết mọi ký tự không thuộc ASCII thành chuỗi escape \u và đặt dấu gạch chéo ngược trước mỗi /. Cả hai đều là JSON hợp lệ và giải mã lại đúng văn bản ban đầu, nhưng chúng làm đầu ra khó đọc và dài hơn. JSON_UNESCAPED_UNICODE giữ nguyên ký tự, còn JSON_UNESCAPED_SLASHES giữ nguyên URL:

Đầu ra:

{"name":"\u308a\u3093\u3054","price":120,"url":"https:\/\/example.com\/fruit\/apple"}
{"name":"りんご","price":120,"url":"https://example.com/fruit/apple"}

Chữ tiếng Việt có dấu cũng bị escape như vậy. Nếu văn bản bị lỗi font (文字化け) sau khi giải mã thì vấn đề không nằm ở escape: ngay từ đầu chuỗi đã không phải UTF-8. json_encode() chỉ nhận UTF-8 và trả về false với mọi thứ khác, như phần về lỗi bên dưới.

Khi mảng thành object thay vì danh sách

Mảng PHP chỉ được mã hóa thành mảng JSON khi khóa của nó đúng là 0, 1, 2... theo thứ tự. Mọi khóa khác đều biến nó thành object JSON. Điều này hay làm người ta bất ngờ sau unset() hoặc array_filter(), vì chúng để lại khoảng trống trong khóa:

Đầu ra:

{"0":"apple","2":"cherry"}
["apple","cherry"]
{"1":"a","2":"b"}
[]
{}
{"0":"a","1":"b"}

Gọi array_values() trước khi mã hóa mỗi khi bên nhận cần một danh sách. Nếu bên nhận cần một object có thể rỗng, dùng new stdClass() hoặc (object) $array để giá trị rỗng vẫn ra {}.

Mã hóa đối tượng và điều khiển JSON bằng JsonSerializable

Một đối tượng thông thường chỉ được mã hóa với các thuộc tính public; thuộc tính protected và private bị bỏ qua. Để quyết định chính xác một đối tượng trông thế nào trong JSON, hãy implement interface JsonSerializable và trả về dữ liệu từ jsonSerialize():

Đầu ra:

{"name":"Ada","nick":null}
{"date":"2026-03-14 09:30:00.000000","timezone_type":3,"timezone":"UTC"}
{
    "id": 7,
    "total": 19.5,
    "created": "2026-03-14T09:30:00+00:00"
}

Một backed enum như enum Status: string được mã hóa thành giá trị của nó ("active"). Pure enum không có giá trị, nên json_encode() thất bại với thông báo "Non-backed enums have no default serialization".

Số nguyên, số thực và chuỗi số

Số nguyên và số thực được viết thành số JSON, còn chuỗi vẫn là chuỗi kể cả khi chứa chữ số. Ba flag thay đổi điều đó:

Đầu ra:

{"price":10}
{"price":10.0}
0.30000000000000004
{"qty":"3","id":"007"}
{"qty":3,"id":7}

JSON_NUMERIC_CHECK chuyển mọi chuỗi số, nên một ID như "007" hay mã bưu chính như "01234" mất các số 0 ở đầu. Hãy chuyển đúng những trường bạn cần bằng (int) thay vì dùng flag này cho cả mảng.

json_encode trả về false: tìm lỗi

json_encode() trả về false khi không mã hóa được giá trị. Nguyên nhân thường gặp là một chuỗi không phải UTF-8 hợp lệ (văn bản đọc từ tệp cũ hoặc cơ sở dữ liệu Latin-1) và các giá trị số thực NAN và INF. json_last_error_msg() cho biết lỗi gì; JSON_THROW_ON_ERROR khiến hàm ném ra JsonException:

Đầu ra:

bool(false)
Malformed UTF-8 characters, possibly incorrectly encoded
{"name":"Caf\ufffd"}
{"name":"Café"}
JsonException: Inf and NaN cannot be JSON encoded

JSON_THROW_ON_ERROR là lựa chọn mặc định tốt hơn trong code mới: một giá trị false không ai kiểm tra rốt cuộc sẽ bị lưu hoặc gửi đi như một chuỗi rỗng.

Trả về JSON từ một API PHP

Một script PHP trả lời bằng JSON đặt header Content-Type trước khi in bất cứ thứ gì, mã hóa một lần rồi dừng:

<?php
header('Content-Type: application/json; charset=utf-8');

$products = [
    ['id' => 1, 'name' => 'りんご', 'price' => 120],
    ['id' => 2, 'name' => 'みかん', 'price' => 80],
];

echo json_encode(['data' => $products], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
exit;

Khi bạn in JSON bên trong thẻ <script> của HTML, hãy thêm JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT. Cách escape dấu gạch chéo mặc định biến </script> thành <\/script>, nhưng lớp bảo vệ đó mất ngay khi ai đó thêm JSON_UNESCAPED_SLASHES, và <!-- trong một giá trị vẫn thay đổi cách trình duyệt phân tích script. Các flag này viết <, >, &, ' và " thành \u003C, \u003E, \u0026, \u0027 và \u0022, và JavaScript đọc lại chúng thành đúng các ký tự đó.

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

Làm sao chuyển một mảng PHP sang JSON?

Truyền mảng vào json_encode(): json_encode(['name' => 'Ada', 'age' => 36]) trả về {"name":"Ada","age":36}. Mảng có khóa 0, 1, 2... theo đúng thứ tự thì thành mảng JSON: json_encode(['a', 'b']) trả về ["a","b"].

Làm sao in JSON dễ đọc (pretty print) trong PHP?

Thêm flag JSON_PRETTY_PRINT: json_encode($data, JSON_PRETTY_PRINT) thụt lề 4 dấu cách và đặt mỗi giá trị trên một dòng riêng. Kết hợp nhiều flag bằng |, ví dụ JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE.

Vì sao json_encode biến chữ tiếng Nhật (hay tiếng Việt có dấu) thành mã \u?

Mặc định, mọi ký tự không thuộc ASCII được viết thành chuỗi escape \uXXXX, nên りんご thành \u308a\u3093\u3054. Kết quả vẫn là JSON hợp lệ, nhưng hãy truyền JSON_UNESCAPED_UNICODE để giữ ký tự dễ đọc.

Vì sao json_encode trả về false?

Thường là do có một chuỗi không phải UTF-8 hợp lệ, hoặc dữ liệu chứa NAN hay INF. Gọi json_last_error_msg() để xem lý do, hoặc truyền JSON_THROW_ON_ERROR để hàm ném ra JsonException thay vì trả về false.

Làm sao để json_encode xuất {} thay vì [] cho mảng rỗng?

Mảng PHP rỗng luôn được mã hóa thành []. Dùng new stdClass() hoặc (object) [] cho một object rỗng, hoặc flag JSON_FORCE_OBJECT, flag này biến mọi mảng trong giá trị thành object.

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