Working With JSON in PHP: json_encode, json_decode, and Common Errors

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? Set json_decode()‘s second parameter accordingly
  • Are you checking json_last_error() after every json_decode() call that handles external data?
  • Using JSON_UNESCAPED_UNICODE when 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.