Skip to content

PHP Tutorial Working with JSON and APIs

json_encode()

Lesson 305 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

json_encode() turns a PHP value into a JSON string.

index.php
PHP
<?php
$user = [
    "id" => 7,
    "name" => "Ana",
    "tags" => ["php", "web"],
    "active" => true,
    "score" => 9.5,
    "manager" => null,
];

echo json_encode($user);
Output
OUTPUT
{"id":7,"name":"Ana","tags":["php","web"],"active":true,"score":9.5,"manager":null}

List or object?

  • An array with keys 0, 1, 2 ... in order becomes a JSON array [...].
  • An array with other keys becomes a JSON object {...}.
index.php
PHP
<?php
echo json_encode(["a", "b"]) . "\n";
echo json_encode([1 => "a", 2 => "b"]) . "\n";   // keys do not start at 0: an object
echo json_encode([]) . "\n";                     // empty array
echo json_encode(new stdClass());                // empty object
Output
OUTPUT
["a","b"]
{"1":"a","2":"b"}
[]
{}

If you filter an array and the keys have gaps, wrap it with array_values() to get a JSON array.

Flags

A second argument sets options. Combine flags with |.

index.php
PHP
<?php
$data = ["name" => "Zoë", "url" => "https://example.com/a/b"];

echo json_encode($data) . "\n";
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\n";
echo json_encode(["a" => 1, "b" => [2, 3]], JSON_PRETTY_PRINT);
Output
OUTPUT
{"name":"Zo\u00eb","url":"https:\/\/example.com\/a\/b"}
{"name":"Zoë","url":"https://example.com/a/b"}
{
    "a": 1,
    "b": [
        2,
        3
    ]
}
FlagEffect
JSON_PRETTY_PRINTIndents the output for people
JSON_UNESCAPED_UNICODEKeeps characters like ë and Hindi letters, instead of \u00eb
JSON_UNESCAPED_SLASHESKeeps / as it is
JSON_THROW_ON_ERRORThrow a JsonException on failure
JSON_NUMERIC_CHECKTurns numeric strings into numbers (avoid, it changes data)
JSON_HEX_TAG, JSON_HEX_AMP, …Safe embedding in HTML (see XSS)
JSON_PRESERVE_ZERO_FRACTIONKeeps 10.0 as 10.0 instead of 10

Errors: always handle failure

json_encode() can fail, for example when text is not valid UTF-8. By default it returns false quietly.

index.php
PHP
<?php
$bad = ["name" => "caf" . chr(233)];   // a Latin-1 byte, not valid UTF-8

var_dump(json_encode($bad));
echo json_last_error_msg() . "\n";

try {
    json_encode($bad, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo "Exception: " . $e->getMessage();
}
Output
OUTPUT
bool(false)
Malformed UTF-8 characters, possibly incorrectly encoded
Exception: Malformed UTF-8 characters, possibly incorrectly encoded

Use JSON_THROW_ON_ERROR in new code, so failures cannot be ignored.

Objects

json_encode() includes an object’s public properties.

index.php
PHP
<?php
class Product
{
    public function __construct(
        public string $name,
        public float $price,
        private string $secretNote = "internal",
    ) {}
}

echo json_encode(new Product("Pen", 12.5));
Output
OUTPUT
{"name":"Pen","price":12.5}

The private property is left out.

Control the output: JsonSerializable

Implement JsonSerializable to decide exactly what is output.

index.php
PHP
<?php
class User implements JsonSerializable
{
    public function __construct(
        private int $id,
        private string $name,
        private string $passwordHash,
    ) {}

    public function jsonSerialize(): array
    {
        return ["id" => $this->id, "name" => $this->name];   // never the hash
    }
}

echo json_encode(new User(1, "Ana", '$2y$10$abc'));
Output
OUTPUT
{"id":1,"name":"Ana"}

Enums and dates

A backed enum becomes its value. A DateTime becomes an object with date and timezone, which is rarely what you want. Format dates yourself:

index.php
PHP
<?php
enum Status: string { case Paid = "paid"; }

$order = [
    "status" => Status::Paid,
    "created" => (new DateTimeImmutable("2026-03-01 10:30:00", new DateTimeZone("UTC")))->format(DATE_ATOM),
];

echo json_encode($order);
Output
OUTPUT
{"status":"paid","created":"2026-03-01T10:30:00+00:00"}

Numbers

PHP floats may print with many digits. The setting serialize_precision = -1 (the default) gives the shortest exact form, so 0.1 stays 0.1.

Never encode secrets

Build the array from an allow-list of fields, so a password hash or token is never included by accident.

lightbulb
Pretty print in development only
JSON_PRETTY_PRINT is nice for humans, but sends more bytes. Use it for debugging and config files, not for API responses.