json_encode() 静默返回 false 而非抛异常,需用 === false 和 json_last_error_msg() 检测;json_decode() 的 $depth 是安全硬边界,设 64 更合理;中文乱码、空数组转对象、大整数丢失须分别用 json_unescaped_unicode、手动转 (object)[]、json_bigint_as_string 解决。

json_encode 会因循环引用或深度超限直接返回 false,不抛异常
PHP 的 json_encode() 在遇到无法序列化的结构(如资源类型、含循环引用的对象、或嵌套层级超过默认限制)时,不会报错或抛出异常,而是静默返回 false。这极易导致后续逻辑误判为“空数据”而非“编码失败”。
- 默认最大深度是 512 层,但实际触发失败往往远低于此——尤其当对象属性间存在隐式引用(如 Doctrine Entity 中的关联关系)
- 没有内置参数可让
json_encode()在超限时抛出Exception,必须手动检查返回值 - 检测方式只能是:
if ($json === false) { echo json_last_error_msg(); },不能用=== null或empty() - 若需控制深度,得先用递归函数预检结构深度,或改用
serialize()+ 自定义 JSON 封装(不推荐,仅调试用)
json_decode 的 $depth 参数不是“建议值”,而是安全硬边界
很多开发者把 $depth 当作性能提示,其实它是防止栈溢出和 DoS 攻击的关键闸门。PHP 8.3+ 虽支持 json_validate() 预检,但不校验深度;真正起作用的只有 json_decode() 执行时的深度截断。
- 设为
64足够覆盖绝大多数业务场景(如三层嵌套的订单+商品+规格),比默认 512 更安全 - 设为
1会直接拒绝所有对象/数组,只允许基本类型(string/number/bool/null),可用于白名单式轻量解析 - 当
json_decode($str, true, $depth)返回null且json_last_error() === JSON_ERROR_DEPTH,说明不是格式错,而是结构太深 - 不要依赖
set_error_handler()捕获警告——json_decode()不触发 E_WARNING,错误只存于内部状态
中文乱码、空数组转对象、大整数丢失:三个高频陷阱的绕过方式
这些不是 bug,而是 RFC 7159 与 PHP 类型系统的天然摩擦点,每个都对应一个明确的选项或前置动作。
- 中文显示为
\u4f60\u597d:必须加JSON_UNESCAPED_UNICODE,没别的办法;mb_convert_encoding()只解决输入编码问题,不解决输出转义 - 空数组
[]被前端当成数组而非对象:PHP 没有JSON_FORCE_OBJECT这种选项,得手动转换 ——$data = empty($data) ? (object)[] : $data;再传给json_encode() - 19 位以上整数变科学计数法或精度丢失:加
JSON_BIGINT_AS_STRING,否则json_decode()会把它转成 float 导致末尾数字归零(如"1234567890123456789"→1.2345678901235E+18)
生产环境别用 JSON_PRETTY_PRINT,日志里也得关
缩进看似友好,但 JSON_PRETTY_PRINT 带来的空格和换行在 HTTP 响应头、Redis 缓存、数据库字段中全是冗余字节,且不可逆压缩。
- API 响应体增加约 20–35% 体积,对移动端或高并发接口是实打实的带宽浪费
- 写入 Redis 时若带缩进,相同数据的
strlen()不同,导致缓存键不一致或误判变更 - 日志中开启美化会导致单行日志跨多行,破坏
tail -f和 ELK 解析;真要调试,用var_dump(json_decode($json, true))更直接 - 唯一合理使用场景:本地开发时
echo '<pre class="brush:php;toolbar:false;">' . htmlspecialchars(json_encode($data, JSON_PRETTY_PRINT)) . '</pre>';
json_encode() 和 json_decode() 前后,而不是指望它们自己扛。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











