Fix lỗi PHP json_decode(): 'expects parameter 1 to be string, null given'

beginner🐘 PHP2026-03-23| PHP 7.x / 8.x, mọi hệ điều hành (Linux, macOS, Windows), mọi framework (Laravel, Symfony, PHP thuần)

Error Message

json_decode() expects parameter 1 to be string, null given
#php#json#decode#parse

Lỗi Gặp Phải

Bạn gọi json_decode() và nhận ngay thông báo lỗi:

json_decode() expects parameter 1 to be string, null given

Hoặc trên PHP 8:

json_decode(): Argument #1 ($json) must be of type string, null given

Hàm nhận được null thay vì một chuỗi JSON. Dòng lệnh gây lỗi thì rõ ràng — nhưng nguyên nhân thực sự đang ẩn ở vài dòng phía trên.

Nguyên Nhân

  • Một API response hoặc kết quả đọc file trả về null hoặc rỗng, và bạn truyền thẳng vào json_decode() mà không kiểm tra. Đây là nguyên nhân phổ biến nhất.
  • Hàm bạn kỳ vọng trả về chuỗi thực ra lại trả về null khi thất bại — file_get_contents(), $request->getContent(), và đọc cột DB đều làm vậy một cách âm thầm.
  • Biến chưa bao giờ được gán giá trị — lỗi đánh máy tên biến, thiếu lệnh gán, hoặc một nhánh điều kiện đã bỏ qua nó hoàn toàn.
  • JSON đến từ đầu vào người dùng hoặc dịch vụ bên ngoài mà không gửi gì cả: POST body rỗng, thiếu query param, hoặc response 4xx không có body.

Cách Sửa 1 — Kiểm Tra Trước Khi Decode

Hãy xác minh giá trị là chuỗi không rỗng trước khi dùng đến json_decode(). Đơn giản, và buộc bạn phải quyết định "thất bại" có nghĩa là gì trong code của mình.

<?php

$raw = file_get_contents('https://api.example.com/data');

if ($raw === false || $raw === null || $raw === '') {
    // Ghi log, ném exception, hoặc return sớm — chọn một cách
    throw new RuntimeException('Failed to fetch JSON data');
}

$data = json_decode($raw, true);

Với đầu vào người dùng từ request:

<?php

$body = $request->getContent(); // Có thể là chuỗi rỗng

if (empty($body)) {
    return response()->json(['error' => 'Empty request body'], 400);
}

$data = json_decode($body, true);

Cách Sửa 2 — Kiểm Tra json_last_error() Sau Khi Decode

Chú ý một cạm bẫy: json_decode() trả về null trong hai tình huống hoàn toàn khác nhau — đầu vào là null, JSON bị lỗi cú pháp. Nếu không kiểm tra, bạn không thể biết điều gì đã xảy ra.

<?php

$data = json_decode($raw, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    throw new RuntimeException('JSON decode failed: ' . json_last_error_msg());
}

Cách này bắt được cú pháp không hợp lệ, encoding bất thường, và response bị cắt ngắn — những lỗi mà nếu không xử lý sẽ âm thầm làm hỏng dữ liệu ở các tầng phía sau.

Cách Sửa 3 — Dùng Null Coalescing Cho Dữ Liệu Tùy Chọn

Đôi khi giá trị bị thiếu là hoàn toàn bình thường — một cột DB có thể null, một trường config tùy chọn. Trong trường hợp đó, hãy cung cấp giá trị dự phòng an toàn thay vì dừng lại:

<?php

// Nếu $row['metadata'] là null, decode một object rỗng thay thế
$metadata = json_decode($row['metadata'] ?? '{}', true);

// Hoặc cho mảng
$tags = json_decode($row['tags'] ?? '[]', true);

Hãy chọn giá trị dự phòng thực sự phù hợp với dữ liệu của bạn. Mặc định về lại null thì không có ý nghĩa gì.

Cách Sửa 4 — Truy Tìm Nguồn Gốc null

Khi nguồn gốc không rõ ràng, hãy dump giá trị ngay trước khi decode và dừng thực thi:

<?php

var_dump($raw); // Có phải null không? false? Chuỗi rỗng?
die();

$data = json_decode($raw, true);

Khi thấy giá trị thực tế, nguyên nhân thường trở nên rõ ràng ngay:

  • file_get_contents() trả về false — sai đường dẫn, không có quyền truy cập, hoặc timeout mạng
  • $_POST['json_data'] không tồn tại — sai tên field, hoặc client gửi application/x-www-form-urlencoded thay vì application/json
  • Cột DB là NULL — row tồn tại nhưng field đó chưa bao giờ được điền
  • Body của cURL response rỗng — server trả về 4xx/5xx không có body

Riêng với cURL, hãy kiểm tra cả mã HTTP status — response 401 hoặc 500 thường có body rỗng:

<?php

$ch = curl_init('https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($response === false || $httpCode !== 200) {
    throw new RuntimeException("API request failed with HTTP $httpCode");
}

$data = json_decode($response, true);

Cách Sửa 5 — Bọc Lại Trong Hàm Helper Để Xử Lý Nhất Quán

PHP 8 đã nâng cấp lỗi này từ cảnh báo thành TypeError đầy đủ, giúp dễ phát hiện hơn trong log. Dù sao đi nữa, nếu bạn decode JSON ở nhiều nơi, hãy tập trung xử lý vào một chỗ:

<?php

function safe_json_decode(?string $json, bool $assoc = true): mixed
{
    if ($json === null || $json === '') {
        return null;
    }

    $data = json_decode($json, $assoc);

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

    return $data;
}

Mọi lệnh decode trong codebase giờ đều đi qua một hàm duy nhất. Lỗi xuất hiện ngay lập tức với thông báo rõ ràng, thay vì lan truyền dưới dạng các giá trị null bí ẩn qua ba tầng gọi hàm.

Kiểm Tra Sau Khi Sửa

Kiểm tra nhanh trong một file thử nghiệm:

<?php

// Nên trả về mảng không có lỗi
$result = json_decode('{"key": "value"}', true);
var_dump($result); // array(1) { ["key"] => string(5) "value" }

// Null guard nên trả về mảng rỗng
$result = json_decode(null ?? '{}', true);
var_dump($result); // array(0) {}

Trong ứng dụng Laravel hoặc Symfony, chạy test suite hoặc gọi trực tiếp endpoint:

curl -X POST https://yourapp.test/api/endpoint \
  -H 'Content-Type: application/json' \
  -d '{"test": true}'

Cũng hãy kiểm tra trường hợp thất bại — gửi body rỗng và xác nhận guard của bạn trả về lỗi 400 hợp lệ thay vì crash.

Phòng Ngừa

Cách sửa thực sự nằm ở nguồn gốc dữ liệu, không phải tại lệnh decode. Bất kỳ JSON nào đến từ API, file, hay đầu vào người dùng đều nên được kiểm tra trước khi chạm tới json_decode(). Dịch vụ bên ngoài đặc biệt không đáng tin — chúng trả về body rỗng khi xác thực thất bại, JSON lỗi cú pháp khi response không đầy đủ, và trang HTML thông báo lỗi khi có sự cố ở phía họ.

Khi cần debug JSON bị lỗi cú pháp, JSON Formatter & Validator trên ToolCraft rất đáng bookmark — dán chuỗi thô vào và nó sẽ chỉ ra lỗi cú pháp chính xác ngay lập tức. Chạy hoàn toàn trên trình duyệt, không upload dữ liệu lên đâu cả.

Những thói quen giúp bạn gần như không bao giờ gặp lỗi này:

  • Bật strict types (declare(strict_types=1);) — PHP 8 ném TypeError trước khi tới json_decode() nếu bạn truyền sai kiểu
  • Dùng typed class properties — nếu $this->jsonData được khai báo là string, gán null sẽ thất bại ngay tại điểm gán, không phải ba lần gọi hàm sau đó
  • Ghi log raw response trước khi decode trong quá trình phát triển — bạn sẽ phát hiện response rỗng hoặc lỗi cú pháp ngay khi chúng xuất hiện
  • Viết unit test gửi null, chuỗi rỗng, và JSON bị lỗi đến mọi endpoint nhận đầu vào để decode — hãy làm các trường hợp ngoại lệ trở nên tường minh

Related Error Notes