JSON and PHP

Learn how PHP converts between JSON text and native PHP data using json_decode and json_encode, the two functions at the heart of most PHP APIs.

PHP and JSON: Two Directions

A typical PHP endpoint does two conversions per request: it receives JSON text and turns it into PHP values with json_decode(), then it turns PHP values back into JSON text with json_encode() before sending a reply. Everything in between — validation, database queries, business logic — works with ordinary PHP arrays and objects.

Decoding JSON with json_decode()

json_decode() takes a JSON string and returns PHP data. Its second argument controls the shape of the result: true returns associative arrays, and the default false returns stdClass objects. Because PHP's $_POST superglobal only understands form-encoded data, a JSON request body must be read manually from the php://input stream.

Reading a JSON request body

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p id="demo"></p>

<script>
// The following PHP code runs on the server, not in the browser.
// It is shown here for reference and does not execute in this client-side sandbox.
/*
<?php
$rawBody = file_get_contents('php://input');
$data = json_decode($rawBody, true);

$name = $data['name'] ?? null;
$email = $data['email'] ?? null;

echo "Received: $name, $email";
*/

document.getElementById("demo").innerHTML = "This example shows server-side PHP code (see the comment above). PHP runs on the server and cannot execute in the browser.";
</script>

</body>
</html>

Encoding PHP Data with json_encode()

json_encode() takes a PHP array or object and produces a JSON string. Before echoing that string, set the response's Content-Type header to application/json so the client knows how to interpret the body. Optional flags change formatting and escaping behavior without changing the underlying data.

Encoding a JSON response

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p id="demo"></p>

<script>
// The following PHP code runs on the server, not in the browser.
// It is shown here for reference and does not execute in this client-side sandbox.
/*
<?php
header('Content-Type: application/json');

$users = [
  ['id' => 1, 'name' => 'Wei Chen'],
  ['id' => 2, 'name' => 'Fatima Noor']
];

echo json_encode($users, JSON_PRETTY_PRINT);
*/

document.getElementById("demo").innerHTML = "This example shows server-side PHP code (see the comment above). PHP runs on the server and cannot execute in the browser.";
</script>

</body>
</html>
  • JSON_PRETTY_PRINT — adds indentation and line breaks, useful for debugging responses in a browser or terminal.
  • JSON_UNESCAPED_SLASHES — keeps forward slashes (e.g. in URLs) as-is instead of escaping them to \/.
  • JSON_UNESCAPED_UNICODE — outputs multi-byte characters directly instead of as \uXXXX escape sequences.
  • JSON_THROW_ON_ERROR — makes json_encode() and json_decode() throw a JsonException on failure instead of silently returning false or null.

Handling Errors in Decoding

json_decode() returns null both when the input is invalid JSON and when the input is the literal JSON value null — so null alone cannot tell you whether something went wrong. Check json_last_error() after decoding, or pass the JSON_THROW_ON_ERROR flag (available since PHP 7.3) and catch the resulting JsonException.

Validating decoded JSON

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p id="demo"></p>

<script>
// The following PHP code runs on the server, not in the browser.
// It is shown here for reference and does not execute in this client-side sandbox.
/*
<?php
$rawBody = file_get_contents('php://input');

try {
  $data = json_decode($rawBody, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
  http_response_code(400);
  echo json_encode(['error' => 'Invalid JSON: ' . $e->getMessage()]);
  exit;
}

echo json_encode(['received' => $data]);
*/

document.getElementById("demo").innerHTML = "This example shows server-side PHP code (see the comment above). PHP runs on the server and cannot execute in the browser.";
</script>

</body>
</html>
ParameterTypePurpose
jsonstringThe raw JSON text to decode
associativebooltrue for arrays, false (default) for stdClass objects
depthintMaximum nesting depth allowed, default 512
flagsintBitmask of options such as JSON_THROW_ON_ERROR
Note: Forget to pass true as the second argument and you'll get a stdClass object back — access its fields with -> (like $data->name), not array syntax. Mixing the two up is one of the most common PHP-and-JSON beginner mistakes.
Note: Decoding JSON does not sanitize it. A successfully decoded value can still contain a string meant to break a SQL query or a file path meant to escape a directory. Validate expected keys and types, and use parameterized queries, before decoded data touches a database or the filesystem.

Exercise: JSON PHP

Which PHP function converts a JSON string into a PHP value?