在 PHP 开发中,经常需要将数据进行编码和解码处理,尤其是当涉及网络传输或文件存储时。json_decode() 是解析 JSON 数据成 PHP 数组或对象的常用函数,而 pack() 函数则可以将数据打包成二进制字符串,方便传输和存储。本文将详细讲解如何将 json_decode() 得到的数组结果用 pack() 打包为二进制数据。
json_decode(string $json, bool $assoc = true)
解析 JSON 字符串,第二个参数为 true 返回关联数组,为 false 返回对象。
pack(string $format, mixed $args...)
根据格式字符,将参数打包成二进制字符串。格式字符决定了每个参数的类型及长度。
假设有如下 JSON 数据:
{
"id": 123,
"temperature": 36.5,
"status": 1
}
我们使用 json_decode() 转换为数组后,希望用 pack() 将其打包成二进制数据,方便网络传输。
<?php
// JSON 数据
$json = '{"id":123,"temperature":36.5,"status":1}';
// 使用 json_decode 解析为关联数组
$data = json_decode($json, true);
// 确认解析结果
// var_dump($data);
// 假设数据格式如下:
// id: 32位无符号整数 (N)
// temperature: 浮点数,32位单精度 (f)
// status: 8位无符号整数 (C)
// 注意:pack 不支持 64位浮点数格式,只能使用单精度或双精度(d)
// 这里选择单精度(f)
$binary = pack(
'NfC', // 格式字符:N - 32位大端无符号整数, f - 浮点数, C - 8位无符号整数
$data['id'],
$data['temperature'],
$data['status']
);
// 输出二进制数据的十六进制表示,方便查看
echo bin2hex($binary);
?>
N 表示 32位无符号大端整数(网络字节序),适合传输和跨平台。
f 表示 32位单精度浮点数。
C 表示 8位无符号整数。
这里将 id 打包为网络字节序的整数,temperature 为浮点数,status 为字节。
为了验证打包的正确性,可以用 unpack() 函数解包:
<?php
// 之前打包后的二进制数据
$binary = pack('NfC', 123, 36.5, 1);
// 解包,格式字符必须与打包时对应
$unpacked = unpack('Nid/ftemperature/Cstatus', $binary);
print_r($unpacked);
?>
输出:
Array
(
[id] => 123
[temperature] => 36.5
[status] => 1
)
如果 JSON 中包含多维数组或者字符串,需要先设计好二进制格式。常见做法是:
定长字段用固定格式打包;
字符串用长度+内容方式打包,例如 pack('N', strlen($str)) . $str;
数组循环打包。
示例:
<?php
$json = '{"users":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]}';
$data = json_decode($json, true);
$binary = '';
foreach ($data['users'] as $user) {
$id = $user['id'];
$name = $user['name'];
$nameLen = strlen($name);
$binary .= pack('N', $id); // id 4字节
$binary .= pack('N', $nameLen); // 名字长度 4字节
$binary .= $name; // 名字字符串
}
echo bin2hex($binary);
?>
json_decode() 解析 JSON 字符串为 PHP 数组;
pack() 根据自定义格式将数据打包为二进制;
需设计好格式,考虑字段长度和类型,特别是字符串需要自带长度信息;
结合 unpack() 验证数据正确性。
更多关于 pack 函数的详细格式说明,可以参考 PHP 官方文档。