json_encode返回null主因是输入类型不合规:非UTF-8字符串、资源句柄、循环引用、不可序列化对象或非法键名,需用json_last_error()定位错误并预处理数据。

json_encode 为什么返回 null?
不是数据本身有问题,而是 json_encode 对输入类型非常敏感:它只接受 UTF-8 编码的字符串、数字、布尔、null、数组(索引或关联)、对象(且属性可访问)。一旦遇到资源、闭包、不可序列化的对象(如 mysqli 实例)、含非法字符(如 GBK 中的中文)的字符串,就静默返回 null。
- 检查返回值是否为
null,再用json_last_error()和json_last_error_msg()定位原因 - 中文乱码常见于非 UTF-8 字符串,用
mb_convert_encoding($str, 'UTF-8', 'GBK')转换后再编码 - 含资源或私有/受保护属性的对象,需实现
JsonSerializable接口,或先用get_object_vars()提取公开属性 - 避免直接传入未过滤的 $_POST 或数据库原始结果——它们可能含二进制字段或 null 字节
json_decode 返回 null 或数组/对象不按预期?
json_decode 默认返回 stdClass 对象,但多数人实际需要数组;更关键的是,只要 JSON 字符串语法错误(哪怕一个逗号多写、引号不配对)、编码不对(BOM 头、UTF-8 不合法字节),它就返回 null,不报错也不提示。
- 始终用第二个参数
true:即json_decode($json, true),强制返回关联数组,避免后续写$obj->key却得到NULL - 用
trim($json)去掉首尾空白,特别是从文件或 curl 响应读取时易带 BOM 或换行 - 检查原始 JSON 是否含单引号(PHP 允许,JSON 标准只认双引号)、注释(JSON 不支持)、尾随逗号(PHP 7.4+ 的 json_decode 仍不支持)
- 从数据库读取 JSON 字段后,别忘了
stripslashes()—— 某些旧版 MySQL 驱动会自动转义反斜杠
处理大 JSON 数据时内存和性能怎么控?
json_encode 和 json_decode 是全量加载的:整个结构必须一次性载入内存。10MB 的 JSON 文件可能撑爆 50MB 内存(PHP 数组开销更大),且解析耗时线性增长。
- 用
json_last_error()替代 try/catch ——json_decode不抛异常,捕获不到错误 - 对超大 JSON(如日志导出、批量导入),改用流式解析库如
ext-jsond(需编译安装)或json-machine(基于迭代器,只读当前节点) - 避免在循环里反复
json_encode同一数组——提前 encode 一次,缓存结果 - 注意
max_input_vars和memory_limit配置,大 JSON 解析失败常是这两个值卡住,而非语法问题
PHP 8.2+ 的 JSON 扩展变化要留意
PHP 8.2 开始,json_decode 对无效浮点数(如 "NaN"、"Infinity")默认拒绝解析(之前静默转为 0),且 json_encode 默认不再允许资源类型(即使你没传,某些对象内部引用也可能触发)。
立即学习“PHP免费学习笔记(深入)”;
- 升级前用
json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR)容错,让非法值转成null而非中断 - 若需兼容旧行为,加
JSON_INVALID_UTF8_IGNORE或JSON_INVALID_UTF8_SUBSTITUTE处理编码问题 - PHP 8.3 引入
JSON_THROW_ON_ERROR标志,可让json_decode抛出JsonException,但要注意已有错误处理逻辑是否冲突
json_decode 当万能转换器,忽略了它对输入纯净度的苛刻要求——尤其当数据来自第三方接口、旧系统导出或用户上传时,预处理比硬解更重要。



















