serialize() 将数组转为 PHP 特有二进制安全字符串格式(如 a:2:{i:0;s:5:"hello";i:1;i:123;}),仅能被 unserialize() 还原,不适用于 JSON 传输或跨语言场景,且不支持资源、闭包,对用户输入反序列化存在安全风险。

serialize() 能直接把数组转成字符串,但结果不是人能读的
PHP 的 serialize() 函数确实能把数组(包括多维、含对象、含资源引用的数组)转成字符串,但它生成的是 PHP 特有的二进制安全序列化格式,比如 a:2:{i:0;s:5:"hello";i:1;i:123;}。这种字符串只能被 PHP 的 unserialize() 安全还原,不能当 JSON 用,也不能直接存进某些数据库字段(比如 MySQL 的 TEXT 类型虽能存,但后续查出来没法被其他语言解析)。
- 只适合 PHP 内部存储或缓存场景(如 Redis 的 string 值、Session 数据、文件缓存)
- 如果数组里有匿名函数、资源(
resource)、闭包或某些扩展对象,serialize()会失败或产生不可预测行为 - PHP 8.1+ 对未声明类型的对象序列化会触发
E_WARNING,注意错误报告级别
常见错误:用 serialize() 当 JSON 用,然后前端解析失败
典型现象是:PHP 里 echo serialize($arr) 输出一串乱码似的字符,前端 JS 调 JSON.parse() 直接报错 Unexpected token a in JSON at position 0——因为开头那个 a: 是 serialize() 的类型标识,不是 JSON。
- 要给前端传数据,必须用
json_encode(),不是serialize() -
json_encode()不支持资源、资源句柄、循环引用;serialize()支持循环引用但不支持资源 - 中文在
json_encode()里默认是 Unicode 转义(\u4f60\u597d),加JSON_UNESCAPED_UNICODE参数可避免
简单示例:对比 serialize 和 json_encode 的输出
$arr = ['name' => '张三', 'scores' => [85, 92]];
echo serialize($arr); // a:2:{s:4:"name";s:6:"张三";s:6:"scores";a:2:{i:0;i:85;i:1;i:92;}}
echo json_encode($arr); // {"name":"张三","scores":[85,92]}
注意:serialize() 中文长度按字节算(UTF-8 下“张三”是 6 字节),所以字符串里出现 s:6:"张三";而 json_encode() 默认输出 UTF-8 原始字节(加了 JSON_UNESCAPED_UNICODE 才会这样)。
反序列化时最常踩的坑:忘记校验来源和类型
unserialize() 是高危函数,如果对用户可控输入(比如 cookie、GET 参数、数据库读出的字段)直接调用,可能触发反序列化漏洞(RCE 或任意类方法调用)。PHP 7.4+ 引入了 unserialize($str, ['allowed_classes' => false]) 来禁用对象反序列化,强烈建议显式设置。
- 永远不要
unserialize($_GET['data'])这样写 - 如果只是存数组,且确定没有对象,用
allowed_classes => [](空数组)更安全 - Redis 缓存里用
serialize()没问题,但取出后务必检查是否为FALSE(反序列化失败返回FALSE,不是异常)
实际用的时候,别只盯着“能不能转”,先想清楚:这串字符串最后谁来读?要不要跨语言?有没有用户输入参与?这几个问题的答案,基本就决定了该用 serialize()、json_encode(),还是干脆用 var_export() + eval()(不推荐)或者 igbinary_serialize()(需扩展)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











