PHP has had native JSON support since version 5.2, with no extra extension needed in most installations. The two main functions are json_encode() and json_decode(), and that’s where most of the confusion for beginners lives, mainly because of one parameter that completely changes the return type.
json_decode(): from JSON string to PHP
// php
$text = '{"name": "Ana", "age": 30}';
$data = json_decode($text);
echo $data->name; // Ana
var_dump($data); // object(stdClass)
By default, json_decode() returns an stdClass object, not an associative array. This surprises a lot of people who expect to access the data as $data['name'].
The second parameter: associative array
If you’d rather work with an array instead of an object, pass true as the second parameter.
// php
$data = json_decode($text, true);
echo $data['name']; // Ana
var_dump($data); // array
This is probably the most commonly used setup day to day, since associative arrays tend to be more convenient to work with in PHP than stdClass objects.
json_encode(): from PHP to JSON string
// php
$data = ["name" => "Ana", "age" => 30];
$text = json_encode($data);
echo $text; // {"name":"Ana","age":30}
Works with both associative arrays and objects. json_encode() automatically decides whether to generate a JSON object ({}) or a JSON array ([]) based on the structure of the PHP data.
A detail that trips people up: an empty array becomes [], not {}
// php
$data = [];
echo json_encode($data); // []
An empty array always becomes [] in JSON, even if your intent was an empty object {}. If you need to guarantee it’s treated as an object, use (object).
// php
$data = (object)[];
echo json_encode($data); // {}
Formatting the output JSON
// php
$data = ["name" => "Ana", "address" => ["city" => "New York"]];
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
JSON_PRETTY_PRINT adds readable indentation. JSON_UNESCAPED_UNICODE prevents accented characters and other special characters from being converted into \uXXXX sequences, which matters for non-English content.
Handling errors
Unlike JavaScript, which throws an exception when parsing fails, PHP’s json_decode() silently returns null on error, with no warning by default. This is a common gotcha.
// php
$data = json_decode("invalid json {");
var_dump($data); // NULL, with no visible error
The problem is that null is also a valid return value for legitimate JSON that literally contains null. So you need to check the error explicitly with json_last_error().
// php
$data = json_decode($text);
if (json_last_error() !== JSON_ERROR_NONE) {
echo "Error decoding JSON: " . json_last_error_msg();
}
json_last_error_msg() returns a readable message about what went wrong (e.g., “Syntax error”, “Malformed UTF-8 characters”).
Common error: UTF-8 encoding
json_encode() fails silently (returning false) if the string contains characters that aren’t valid UTF-8, which is common when data comes from a database configured with a different encoding (like Latin1).
// php
$data = ["name" => mb_convert_encoding("Ana", "ISO-8859-1", "UTF-8")];
$text = json_encode($data);
var_dump($text); // false
echo json_last_error_msg(); // Malformed UTF-8 characters
How to fix it: make sure your data is in UTF-8 before calling json_encode(), converting it with mb_convert_encoding() if needed, or fixing the database encoding at the source.
Quick checklist
- Do you know whether you need an object (
stdClass) or an associative array? Setjson_decode()‘s second parameter accordingly - Are you checking
json_last_error()after everyjson_decode()call that handles external data? - Using
JSON_UNESCAPED_UNICODEwhen the content has accented characters? - Confirmed the data is in UTF-8 before calling
json_encode()?
To quickly validate a JSON before using it in your PHP code, paste it into JSON Validator.