How to Handle JSON Errors in PHP

Practical advice from AriZone

In a learning integration, a shop receives a supplier's response but sees an empty value instead of the expected status. The developer adds a fallback meaning “no product”, and a damaged response silently becomes a business decision. JSON errors in PHP should be separated from valid data so that an exchange failure is not disguised as a missing record. We will explore this through a small local example without contacting third-party services.

The goal is to distinguish three situations: the document could not be decoded, the document was read but its structure does not match the agreement, or the structure is correct and processing can continue. These have different causes and different next steps. The example does not change a catalogue, process payments or implement a complete API client. It can serve as the basis for a separate test before modifying an integration.

Establish the boundary between transport and data first

In a real exchange, before decoding you check whether the request completed, which HTTP status was received and which content type the server returned. A proxy error page may contain HTML even where JSON was expected. Do not try to repair it by searching for braces in the text: investigate why that response was returned rather than accidentally extracting a fragment that resembles a document.

Keep separate indicators for connection failures and decoding failures. For example, a diagnostic message might contain the operation name, response status and an internal request identifier. Do not automatically write the entire response to a general log: it may contain addresses, tokens or other private data. Log access and retention also require carefully considered rules.

The source for our test is already known: it is an ordinary string defined in the file. Network checks are therefore deliberately absent here. In production code, add them before this snippet according to the library that performs the request. Do not carry this learning simplification into a working integration, and do not resend an order merely because its response could not be read.

Make decoding failures explicit

The official PHP manual describes json_decode and JsonException. The JSON_THROW_ON_ERROR flag was introduced in PHP 7.3; that is the feature's availability boundary, not a recommendation to use an old version. The exercise requires a supported PHP version with this capability and access to a local terminal. Administrator permissions, additional packages and database access are unnecessary.

Create a new json-demo.php file in a test directory. Do not use the name of an existing integration file, which could accidentally be overwritten. This code assumes an ordinary file without a namespace declaration; inside a namespace, import JsonException or use its fully qualified name. The raw string and status value are examples: replace them according to your own response contract.

<?php
$raw = '{"status":"ready"}';
try {
    $data = json_decode($raw, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
    echo "Invalid JSON", PHP_EOL;
    exit(1);
}
if (!is_array($data) || !isset($data['status'])
    || !is_string($data['status'])) {
    echo "Unexpected structure", PHP_EOL;
    exit(1);
}
echo "Accepted", PHP_EOL;

The flag turns a decoding failure into an explicit exception that this example catches. Successful decoding does not itself guarantee the required fields, so the result's type, the presence of status and that value's type are checked afterwards. The second argument, true, selects associative arrays for JSON objects. Messages are printed only for this local exercise, not for visitors to a live website.

Run the syntax check and the test itself from the directory containing the new file. The first command does not check business logic, so the second is necessary too. If php cannot be found, use your development environment's configured terminal or determine the path to your interpreter. Do not install arbitrary packages just to make the command run.

php -l json-demo.php
php json-demo.php

Collect cases that must not be confused

The initial document should reach the “Accepted” branch. Then change only the raw string, one case at a time: remove the closing brace, provide JSON with a numeric status, supply an empty object, and separately the string null. A damaged document should reach the decoding branch, while valid but unsuitable structures should produce “Unexpected structure”. These are test expectations, not a report of execution on your server.

Valid JSON null deserves particular attention. Without explicit error handling, a null value can represent either the document's data or failed decoding. Do not use a comparison of the result with null alone as a universal error detector. Likewise, an empty array, an empty object and a missing required field must not automatically mean the operation succeeded.

Our contract checks only a string-valued status. In a real integration, you must also restrict allowed values and check required identifiers and the types of nested fields. For example, do not treat an unfamiliar status as confirmation of an order. Define separate behaviour for new values so that a supplier's contract change does not trigger an accidental action in the shop.

Move the rule into the integration without unsafe substitutions

Before making changes, preserve the working code version and review the Git commit. Perform the exercise on a test copy with learning responses rather than real orders. Add tests for a correct document, damaged syntax and an incorrect field type. In logs, separate the failure's cause from its technical details; show external users an understandable message without internal paths or secrets.

Do not repair JSON by globally replacing single quotes with double quotes: this can change text values. Do not substitute an empty array after every exception if downstream code treats it as normal data. Recovery must be explicit: pause the particular operation, offer another check or pass the case for investigation. The approach depends on the operation's consequences and its retry rules.

Conclusion: reliability starts with a clear boundary between a damaged document and an incorrect contract, not with a complex parser. If an integration behaves unpredictably, AriZone can help locate the failure and prepare checks before the fix. To roll back, restore the previous version of the specific change rather than disabling data validation throughout the application.

Discussion

Leave a comment

Add a comment

Your email will not be published. Required fields are marked *.

Cloudflare Turnstile spam protection