← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

json_decode()

PHP PHP 7.3+ Beginner
debt(d5/e1/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and rector as the tools that catch the missing JSON_THROW_ON_ERROR or absent json_last_error() check. These are specialist static analysis tools, not default linters or the compiler, placing this squarely at d5.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix is a direct one-line replacement: add JSON_THROW_ON_ERROR (and optionally true for assoc mode) to the existing json_decode call. No structural refactor is required.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The issue is call-site specific — each json_decode() call must be updated individually, but the fix is contained to those call sites. The problem does not reshape architecture or propagate widely beyond the components that parse JSON.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception field identifies the core trap: developers assume null return means null input, not a parse failure — meaning invalid JSON silently passes as valid decoded data. This contradicts the intuition from most other parsing functions in PHP and other languages that raise errors or return false on failure, making this a serious behavioural contradiction that competent developers routinely get wrong.

About DEBT scoring →

Also Known As

json_decode() PHP JSON parsing json_encode

TL;DR

Parses a JSON string into a PHP value — a safe alternative to unserialize() for structured data exchange.

Explanation

json_decode($json, true) parses a JSON string, returning an associative array (true) or stdClass object (false/null). Unlike unserialize(), it cannot instantiate arbitrary PHP objects or invoke magic methods, making it safe for untrusted input. Always check json_last_error() === JSON_ERROR_NONE after decoding, or use JSON_THROW_ON_ERROR (PHP 7.3+) to throw a JsonException on malformed input. Use json_encode() with JSON_THROW_ON_ERROR on the output side.

Common Misconception

json_decode() always returns null only when the input is null. It also returns null for malformed JSON, and in PHP < 7.3 gives no indication of why. Always follow json_decode() with a json_last_error() check, or pass JSON_THROW_ON_ERROR in PHP 7.3+ to get an exception instead.

Why It Matters

json_decode() returns null both for valid JSON null and for invalid JSON — callers who do not check json_last_error() silently process null as if it were valid decoded data.

Common Mistakes

  • Not checking json_last_error() after decoding — null from a malformed JSON string is indistinguishable from JSON null.
  • Using the second argument (assoc=true) inconsistently — mixing object and array access patterns.
  • Not setting JSON_THROW_ON_ERROR flag (PHP 7.3+) — eliminates the need to manually check json_last_error().
  • Not validating the decoded structure — a valid JSON string may decode to a type or shape the application does not expect.

Code Examples

✗ Vulnerable
// Silent failure on invalid JSON:
$data = json_decode($input);
$name = $data->name; // Fatal error or null — json_last_error() not checked

// Safe:
$data = json_decode($input, flags: JSON_THROW_ON_ERROR);
// JsonException thrown on invalid JSON
✓ Fixed
// Always pass true for associative array (avoids stdClass)
$data = json_decode($json, true);

// Check for errors
if (json_last_error() !== JSON_ERROR_NONE) {
    throw new \InvalidArgumentException('Invalid JSON: ' . json_last_error_msg());
}

// PHP 7.3+ — throw on error
try {
    $data = json_decode($json, true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
    throw new \InvalidArgumentException('Invalid JSON', previous: $e);
}

// Encode with useful flags
$json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);

Tags


Added 15 Mar 2026
Edited 22 Mar 2026
Views 51
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 3 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 1 ping S 2 pings M 2 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 7 Perplexity 6 Scrapy 6 SEMrush 5 Unknown AI 4 Ahrefs 4 ChatGPT 4 Majestic 2 Google 2 Claude 2 Meta AI 1 Bing 1 PetalBot 1
crawler 40 crawler_json 4 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Use json_decode($json, true, 512, JSON_THROW_ON_ERROR) — the flags make it throw JsonException on invalid JSON instead of silently returning null, and associative array mode avoids stdClass surprises
📦 Applies To
PHP 7.3+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
json_decode without JSON_THROW_ON_ERROR; checking json_last_error() after decode; accessing properties on potentially null decode result
Auto-detectable: ✓ Yes phpstan rector
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✓ Auto-fixable Fix: Low Context: Line
CWE-20


✓ schema.org compliant