SimpleRPC 序列化不一致源于客户端与服务端未统一 JSON 编码/解码函数、参数及上下文,如缺失 JSON_UNESCAPED_UNICODE 或 JSON_THROW_ON_ERROR,或浮点精度、UTF-8 处理、NaN/INF 兼容性差异所致。

SimpleRPC 为什么会出现序列化不一致?
Hyperf 的 SimpleRPC 并非官方核心组件,而是社区或自研封装的轻量级 RPC 方案(常基于 TCP + JSON),它不强制约束序列化行为。当客户端和服务端未显式约定序列化方式时,极易出现:服务端用 json_encode() 输出,客户端却用 unserialize() 解析;或双方都用 json_decode(),但一方启用了 JSON_UNESCAPED_UNICODE,另一方没启用,导致中文乱码或解析失败。
检查并统一两端的序列化配置项
关键不是“选哪个序列化方式”,而是确保两端使用完全相同的函数、参数和上下文:
- 确认客户端和服务端都调用
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),且服务端响应体不含额外空格或 BOM - 客户端解码必须用
json_decode($raw, true, 512, JSON_THROW_ON_ERROR),不能省略JSON_THROW_ON_ERROR—— 否则静默失败,你只看到null - 若传输含浮点数,注意 PHP 版本差异:
json_encode(0.1)在 PHP 7.4 和 8.1 中可能输出"0.1"或"0.10000000000000000555",建议业务层对 float 字段做round($v, 10)预处理 - 避免在序列化前手动调用
utf8_encode()或mb_convert_encoding()——json_encode()已默认要求 UTF-8 输入
绕过 SimpleRPC 自动序列化的最稳做法
与其依赖封装层的“自动序列化”,不如主动接管:
- 服务端返回前,明确用
json_encode()生成字符串,再 write 到 socket,header 显式设为Content-Type: application/json; charset=utf-8 - 客户端读取原始响应体后,直接传给
json_decode(),跳过任何中间的unserialize()、yaml_parse()或框架自动反序列化逻辑 - 若协议层有自定义包头(如长度前缀),确保解包逻辑在序列化解析之前完成,否则
json_decode()会因开头多出几个字节而失败 - 在开发环境开启
error_reporting(E_ALL)并捕获json_last_error_msg(),比靠日志猜“解析失败”快得多
跨语言调用时最容易被忽略的细节
如果你的 SimpleRPC 要对接 Python/Go 客户端,PHP 端必须注意:
-
json_encode()默认不处理NaN、INF、-INF—— 这些值在 JSON 中非法,PHP 会静默转成null,而 Python 的json.loads()直接抛异常 - 关联数组(
['a' => 1])会被编码为 JSON 对象,索引数组([1,2,3])才为 JSON 数组。若客户端强依赖数组类型,PHP 端需用array_values()强制重置键 - 空数组
[]和空对象{}在语义上不同,但某些 SimpleRPC 封装会把两者都转成空对象,务必在契约文档里写死预期结构
真正卡住人的往往不是“怎么序列化”,而是“哪一端悄悄改了默认行为”。每次上线前,用 tcpdump -A port 9501 抓一次原始 TCP 流,肉眼核对 payload 是否符合 JSON 规范,比查十页文档更可靠。


















