PHP JSON: Returning Data Quickly and Without Errors

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Debugging an API on the Fly: Why Is Your JSON Returning with an Error?

\n\n

Have you ever sat at three in the morning, staring at a blank Postman screen, thinking: "Why is my PHP script returning HTML instead of JSON?"? If so — you are not alone. The topic Returning JSON from a PHP Script on Stack Overflow has gathered tens of thousands of views, and for good reason. Every second beginner backend developer steps on the same rake: forgotten headers, garbage output, incorrect Content-Type.

\n\n

In this article, we won't just copy a response from a forum. We will break down how to return JSON from PHP correctly, quickly, and without surprises. You will learn why exit(json_encode($data)) can let you down, how to save milliseconds on serialization, and what to do if JSON suddenly "breaks".

\n\n

Ready? Let's go.

\n\n

Anatomy of a Proper JSON Response

\n\n

Let's start with the basics. Here's how not to do it:

\n\n
<?php\n$data = ['status' => 'ok', 'message' => 'Hello!'];\necho json_encode($data);\n?>
\n\n

Why is this bad? First, there is no Content-Type header. The browser or client may interpret the response as HTML or text. Second, if there was any whitespace, echo, or warning in the code before this, the JSON will break.

\n\n

The correct minimal template looks like this:

\n\n
<?php\nheader('Content-Type: application/json; charset=utf-8');\n$data = ['status' => 'ok', 'message' => 'Hello!'];\necho json_encode($data, JSON_UNESCAPED_UNICODE);\nexit;\n?>
\n\n

Note the JSON_UNESCAPED_UNICODE — it keeps Cyrillic readable instead of turning it into \\u043F\\u0440\\u0438\\u0432\\u0435\\u0442. And exit — a safeguard against accidental output after the response.

\n\n

Headers: Not Just Content-Type

\n\n

For JSON performance optimization, add a couple more headers:

\n\n
header('Content-Type: application/json; charset=utf-8');\nheader('X-Content-Type-Options: nosniff');\nheader('Cache-Control: no-cache, must-revalidate');
\n\n

X-Content-Type-Options: nosniff prevents the browser from "guessing" the content type — this is for security. And Cache-Control is useful for dynamic data so the client doesn't cache an outdated response.

\n\n

Error Handling: When JSON_ENCODE Fails

\n\n

The json_encode function returns false on failure. And this is where things get interesting. If you simply do echo json_encode($data) and get an empty string in response — the client will be left puzzled.

\n\n

Always check the result:

\n\n
$json = json_encode($data, JSON_UNESCAPED_UNICODE);\nif ($json === false) {\n    http_response_code(500);\n    echo json_encode(['error' => 'JSON encoding failed: ' . json_last_error_msg()]);\n    exit;\n}\necho $json;\nexit;
\n\n

By the way, json_last_error_msg() will return a clear string: "Malformed UTF-8 characters" or "Inf and NaN cannot be JSON encoded". This will save hours of debugging.

\n\n

Deeply Nested Data and Recursion

\n\n

Another problem is circular references in objects. If you pass an object with mutual references, json_encode will throw an error. Solution: use JSON_PARTIAL_OUTPUT_ON_ERROR or pre-convert the object to an array.

\n\n
$json = json_encode($complexObject, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR);
\n\n

But be careful: partial output may be incomplete. It's better to fix the data structure.

\n\n

Optimizing JSON Performance in PHP

\n\n

Now let's move to the most interesting part — how to speed up returning JSON from PHP.

\n\n

1. Caching Serialized JSON

\n\n

If the data changes rarely (directories, configs, city lists), don't serialize them every time. Save the ready JSON to a file, Memcached

Blogs

Book Recommendations