PHP中JSON响应含不可见字符,json_decode失败如何解决?
解决JSON解析时的UTF-8 BOM问题
问题背景
肉眼可见的JSON响应格式正常:
{ "fault": { "code" : "Application Error", "message" : "Generic Error Message" } }
但使用json_decode()解析时返回null,通过json_last_error()调试得到错误:Syntax error, malformed JSON。进一步排查发现,JSON字符串开头存在不可见的UTF-8 BOM字符()。
尝试过自定义清理函数、stripslashes、html_entity_decode等方法均无法移除该字符,且Postman测试相同请求可正常解析,但PHP CURL和GuzzleHTTP请求均遇到相同问题。
解决方案
1. 直接检测并移除BOM字符
UTF-8 BOM是固定的三字节序列\xEF\xBB\xBF,可以直接判断并截取:
$response = curl_exec($curl); // 检查开头是否存在BOM并移除 if (strlen($response) >= 3 && substr($response, 0, 3) === "\xEF\xBB\xBF") { $response = substr($response, 3); } // 解析JSON $decodedData = json_decode($response, true);
2. 利用编码转换去除BOM
使用mb_convert_encoding将内容重新转换为UTF-8,自动去除BOM:
$response = curl_exec($curl); // 转换编码时自动移除BOM $response = mb_convert_encoding($response, 'UTF-8', 'UTF-8'); $decodedData = json_decode($response, true);
3. 让服务端返回不带BOM的内容(推荐)
在请求头中添加Accept-Charset: utf-8,明确告诉服务端返回标准UTF-8编码(不带BOM)的内容:
$curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => 'https://example.com/?reference=Test', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS =>'example', CURLOPT_HTTPHEADER => array( 'Accept: Application/json', 'Accept-Charset: utf-8', // 添加此行 'Subscription-Key: redacted', 'SOAPAction: example', 'Content-Type: text/plain', 'Cookie: Cookiesession=redacted' ), )); $response = curl_exec($curl); $decodedData = json_decode($response, true);
4. 移除开头所有不可见控制字符
如果除了BOM还有其他不可见控制字符,用正则表达式匹配移除:
$response = curl_exec($curl); // 移除开头的所有Unicode控制字符 $response = preg_replace('/^\p{C}+/u', '', $response); $decodedData = json_decode($response, true);
补充说明
Postman会自动处理响应中的BOM字符,而PHP默认不会自动去除UTF-8 BOM,因此需要手动干预处理。
内容的提问来源于stack exchange,提问作者rjbathgate
相关产品推荐
相关产品推荐

