json_encode($value) returns the JSON text for a PHP value. An associative array becomes a JSON object, a list (keys 0, 1, 2...) becomes a JSON array, and strings, numbers, true, false and null become their JSON equivalents.
Output:
{"name":"Ada","age":36,"langs":["php","js"],"admin":true,"manager":null}
string
The result is a plain string, ready to send to a browser, store in a file or a database column, or pass to another program. To turn JSON back into PHP, use json_decode().
Pretty print JSON
json_encode() takes flags as its second argument. JSON_PRETTY_PRINT adds line breaks and 4-space indentation, which is what you want in a config file or a debug log. Combine several flags with |:
Output:
{
"app": "shop",
"debug": false,
"db": {
"host": "localhost",
"port": 3306
},
"tags": []
}
Keep Japanese and other UTF-8 text readable
By default json_encode() writes every non-ASCII character as a \u escape and puts a backslash before every /. Both are valid JSON and decode back to the same text, but they make the output hard to read and longer. JSON_UNESCAPED_UNICODE keeps the characters, and JSON_UNESCAPED_SLASHES keeps URLs as they are:
Output:
{"name":"\u308a\u3093\u3054","price":120,"url":"https:\/\/example.com\/fruit\/apple"}
{"name":"りんご","price":120,"url":"https://example.com/fruit/apple"}
If Japanese text looks garbled (文字化け) after decoding, the problem is not the escapes: the string was not UTF-8 to begin with. json_encode() only accepts UTF-8 and returns false for anything else, as shown in the section on errors.
When an array becomes an object instead of a list
A PHP array is encoded as a JSON array only when its keys are exactly 0, 1, 2... in order. Any other keys make it a JSON object. That catches people out after unset() or array_filter(), which leave gaps in the keys:
Output:
{"0":"apple","2":"cherry"}
["apple","cherry"]
{"1":"a","2":"b"}
[]
{}
{"0":"a","1":"b"}
Call array_values() before encoding whenever the receiving code expects a list. If it expects an object that may be empty, use new stdClass() or (object) $array so an empty value still comes out as {}.
Encode an object and control its JSON with JsonSerializable
A plain object is encoded with its public properties only; protected and private ones are skipped. To decide exactly what an object looks like in JSON, implement the JsonSerializable interface and return the data from jsonSerialize():
Output:
{"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"
}
A backed enum such as enum Status: string encodes as its value ("active"). A pure enum has no value, so json_encode() fails on it with "Non-backed enums have no default serialization".
Numbers, floats and numeric strings
Integers and floats are written as JSON numbers, and strings stay strings even when they contain digits. Three flags change that:
Output:
{"price":10}
{"price":10.0}
0.30000000000000004
{"qty":"3","id":"007"}
{"qty":3,"id":7}
JSON_NUMERIC_CHECK converts every numeric string, so an ID like "007" or a postcode like "01234" loses its leading zeros. Convert the fields you mean with (int) instead of using it on a whole array.
json_encode returns false: find the error
json_encode() returns false when it cannot encode the value. The usual causes are a string that is not valid UTF-8 (text read from an old file or a Latin-1 database) and the float values NAN and INF. json_last_error_msg() says what went wrong; JSON_THROW_ON_ERROR makes it throw a JsonException instead:
Output:
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 is the better default in new code: a false that nobody checks ends up stored or sent as an empty string.
Return JSON from a PHP API
A PHP script that answers with JSON sets the Content-Type header before printing anything, encodes once, and stops:
<?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;
When you print JSON inside an HTML <script> tag instead, add JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT. The default slash escaping turns </script> into <\/script>, but that protection is gone as soon as someone adds JSON_UNESCAPED_SLASHES, and <!-- in a value still changes how the browser parses the script. The flags write <, >, &, ' and " as \u003C, \u003E, \u0026, \u0027 and \u0022, which JavaScript reads back as the same characters.
Frequently Asked Questions
How do I convert a PHP array to JSON?
Pass it to json_encode(): json_encode(['name' => 'Ada', 'age' => 36]) returns {"name":"Ada","age":36}. An array with keys 0, 1, 2... in order becomes a JSON array instead: json_encode(['a', 'b']) returns ["a","b"].
How do I pretty print JSON in PHP?
Add the JSON_PRETTY_PRINT flag: json_encode($data, JSON_PRETTY_PRINT) indents with 4 spaces and puts each value on its own line. Combine flags with |, for example JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE.
Why does json_encode turn Japanese text into \u codes?
By default every non-ASCII character is written as a \uXXXX escape, so りんご becomes \u308a\u3093\u3054. It is still valid JSON, but pass JSON_UNESCAPED_UNICODE to keep the characters readable.
Why does json_encode return false?
Usually because a string is not valid UTF-8, or the data contains NAN or INF. Call json_last_error_msg() to see the reason, or pass JSON_THROW_ON_ERROR so it throws a JsonException instead of returning false.
How do I make json_encode output {} instead of [] for an empty array?
An empty PHP array always encodes as []. Use new stdClass() or (object) [] for an empty object, or the JSON_FORCE_OBJECT flag, which turns every array in the value into an object.