PHPJSON怎么解码失败_php解决json_decode报错的原因【解答】

3次阅读

json_decode() 解析失败默认静默返回 NULL,须用 json_last_error() 检查错误码;常见原因包括语法错误、utf-8 编码损坏、嵌套过深、内存不足及输入非标准 json 字符串

PHPJSON怎么解码失败_php解决json_decode报错的原因【解答】

json_decode() 返回 null 却没报错

这是最常被忽略的问题:phpjson_decode() 在解析失败时默认静默返回 null,不抛异常、不打日志,容易误判为“数据为空”而非“解码失败”。

  • 必须立刻用 json_last_error() 检查错误码,不能只靠 === null 判断
  • 常见错误码:JSON_ERROR_SYNTAX(非法 JSON)、JSON_ERROR_UTF8(UTF-8 编码损坏,比如 GBK 混入)
  • 如果输入是用户提交的 POST body 或文件内容,先用 trim() 去首尾空白——bom 头或换行符会导致 JSON_ERROR_SYNTAX
  • 示例:
    $json = file_get_contents('data.json');<br>$data = json_decode($json, true);<br>if ($data === null && json_last_error() !== JSON_ERROR_NONE) {<br>    throw new RuntimeException('JSON 解码失败: ' . json_last_error_msg());<br>}

中文乱码或 JSON_ERROR_UTF8 错误

PHP 要求输入字符串必须是合法 UTF-8。很多接口数据库导出的数据实际是 GBK/GB2312,直接传给 json_decode() 就会触发 JSON_ERROR_UTF8

  • 别用 iconv('GBK', 'UTF-8//IGNORE', $str) ——//IGNORE 会丢字,且 PHP 8+ 已弃用该写法
  • 推荐用 mb_convert_encoding($str, 'UTF-8', 'auto'),它能自动识别 GBK/GB2312/UTF-8 等编码
  • 若确定来源是 GBK,且环境支持,可用 mb_convert_encoding($str, 'UTF-8', 'GBK')
  • 注意:mysql 查询结果若字段是 gbk_chinese_ci,需在 pdo 连接时设 charset=gbk,或查询后统一转码

嵌套过深或超大 JSON 导致内存/深度限制报错

PHP 默认限制 JSON 解析深度为 512 层,且受 memory_limit 影响。遇到深层嵌套对象或几百 MB 的 JSON 文件,json_decode() 可能返回 null,但 json_last_error()JSON_ERROR_DEPTHJSON_ERROR_STATE_MISMATCH(常因内存不足中断解析)。

  • 调大深度:PHP 7.3+ 支持第三个参数 $depth,如 json_decode($json, true, 2048)
  • 超大 JSON 不要一次性 file_get_contents() 加载——改用流式解析库(如 jsonstream),或分块读取 + 正则切分(仅限结构简单场景)
  • 确认 memory_limit 足够:一个 100MB 的 JSON 解析后数组可能占 300MB+ 内存
  • json_last_error_msg() 查具体原因,别只看 null

布尔值、null、数字被当成字符串传入

前端 JS 有时把 truefalsenull 当作字符串发过来,比如 "true""null",后端没校验就直接 json_decode(),结果得到字符串而非对应类型。

立即学习PHP免费学习笔记(深入)”;

  • 典型现象:json_decode('"true"', true) 返回 "true"(字符串),不是布尔 true
  • 这不是 json_decode() 的问题,而是输入本身不符合 JSON 规范——合法 JSON 的布尔字面量不带引号
  • 解决方案:前端修复;或后端加预处理,用正则替换 "true"true(慎用,易误伤)
  • 更安全的做法:用 filter_var($str, FILTER_VALIDATE_BOOLEAN) 或严格比对再转换,不依赖 JSON 解析

真正难的不是写 json_decode(),而是你永远不知道传进来的是不是“看起来像 JSON”的字符串——BOM、编码混杂、半截 JSON、前端手拼字符串,这些都得在 decode 前兜住。多打一行 json_last_error_msg(),省掉半小时翻日志。

text=ZqhQzanResources