首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP JSON 解析失敗排查:BOM 與隱形字元完整解決方案

     編輯:PHP 相關知識

問題現象

合法 JSON 字串經 json_decode() 解析回傳 null,json_last_error() 回傳 JSON_ERROR_SYNTAX。檢視原始碼無異常,但 Vim 顯示 <feff>、xxd 發現 EF BB BF 三位元組前綴。

根本原因:UTF-8 BOM (Byte Order Mark)

編碼BOM 十六進制Vim 顯示
UTF-8EF BB BF<feff>
UTF-16LEFF FE<feff>
UTF-16BEFE FF<feff>
UTF-32LEFF FE 00 00<feff>
UTF-32BE00 00 FE FF<feff>

BOM 原意標示位元組序,但 JSON RFC 8259 規範禁止 BOM。PHP json_decode() 不自動處理 BOM,導致解析失敗。

檢測方法

Linux 指令檢測

# 查找含 BOM 檔案
grep -r -l $'\xEF\xBB\xBF' /path/to/project

# 十六進制檢視
xxd suspicious.json | head -5

PHP 程式檢測

function hasBom($filepath) {
    $fp = fopen($filepath, 'rb');
    $bom = fread($fp, 3);
    fclose($fp);
    return $bom === "\xEF\xBB\xBF";
}

// 批次掃描
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('/path'));
foreach ($iterator as $file) {
    if ($file->isFile() && hasBom($file->getPathname())) {
        echo "發現 BOM: " . $file->getPathname() . PHP_EOL;
    }
}

移除方案

Vim 互動移除

:set nobomb    " 移除 BOM
:w             " 儲存
:set bomb?     " 查詢狀態

PHP 批次移除腳本

function removeBom($filepath) {
    $content = file_get_contents($filepath);
    if (substr($content, 0, 3) === "\xEF\xBB\xBF") {
        $content = substr($content, 3);
        file_put_contents($filepath, $content);
        return true;
    }
    return false;
}

// 遞迴處理目錄
function cleanDirectory($dir) {
    $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
    foreach ($iterator as $file) {
        if ($file->isFile() && in_array($file->getExtension(), ['php', 'json', 'js', 'css', 'html', 'xml'])) {
            if (removeBom($file->getPathname())) {
                echo "已清理: {$file->getPathname()}\n";
            }
        }
    }
}

IDE 設定預防(以 PhpStorm 為例)

  1. File → Settings → Editor → File Encodings
  2. Global Encoding: UTF-8
  3. Project Encoding: UTF-8
  4. 取消勾選 Add BOM for new files

Git Hooks 阻止提交 BOM

#!/bin/sh
# .git/hooks/pre-commit

files=$(git diff --cached --name-only --diff-filter=ACM)
for file in $files; do
    if head -c 3 "$file" | xxd -p | grep -q '^efbbbf'; then
        echo "錯誤: $file 含有 UTF-8 BOM,請移除後再提交"
        exit 1
    fi
done
exit 0

相容性處理:解析前自動清理

function safeJsonDecode($json, $assoc = false, $depth = 512, $options = 0) {
    // 移除可能的 BOM
    $json = ltrim($json, "\xEF\xBB\xBF\xFE\xFF\xFF\xFE\x00\x00");
    return json_decode($json, $assoc, $depth, $options);
}

// 使用
$data = safeJsonDecode(file_get_contents('config.json'));

最佳實踐總結

  1. 編輯器統一設定 UTF-8 無 BOM
  2. 專案加入 .editorconfig:charset = utf-8, insert_final_newline = true
  3. CI/CD 整合 BOM 檢測,阻止問題程式碼上線
  4. Windows 避免使用記事本編輯程式碼,改用 VS Code、Sublime、PhpStorm
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved