JSON还是Serialize:PHP数组存储该如何选择?(完整指南)

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:PHP开发者的永恒难题

\n\n

每位PHP开发者都曾面临这样的问题:"如何将数组保存到文件、数据库或缓存中?"在Stack Overflow上,"Preferred method to store PHP arrays (json_encode vs serialize)" 这个问题获得了数千次浏览和数十个回答。这并不奇怪,因为在json_encode()和serialize()之间做出选择,会影响代码的性能、兼容性甚至安全性。

\n\n

本文将通过实际案例剖析这两种方法,对比它们的优缺点,并给出明确的使用建议。让我们开始吧!

\n\n

什么是PHP中的序列化?

\n\n

序列化是将复杂数据结构(数组、对象)转换为可存储或传输的字符串的过程。反向过程称为反序列化。

\n\n

PHP为此提供了两种主要工具:

\n\n
    \n
  • serialize() / unserialize() — PHP内置机制。
  • \n
  • json_encode() / json_decode() — 处理JSON格式。
  • \n
\n\n

乍看之下两者功能相同,但细节决定成败。

\n\n

示例1:简单关联数组

\n\n

我们从最简单的案例开始——包含用户数据的关联数组:

\n\n
<?php\n$user = [\n    'name' => '阿列克谢',\n    'email' => 'alex@example.com',\n    'age' => 30,\n    'is_admin' => false\n];\n\n// 序列化\n$serialized = serialize($user);\necho $serialized . PHP_EOL;\n// 输出:a:4:{s:4:"name";s:14:"阿列克谢";s:5:"email";s:17:"alex@example.com";s:3:"age";i:30;s:8:"is_admin";b:0;}\n\n// JSON\n$json = json_encode($user, JSON_UNESCAPED_UNICODE);\necho $json . PHP_EOL;\n// 输出:{"name":"阿列克谢","email":"alex@example.com","age":30,"is_admin":false}\n?>
\n\n

在此阶段已可见差异:serialize()生成的字符串更"杂乱",包含数据类型(s:表示字符串,i:表示整数,b:表示布尔值)。而JSON则清晰可读。

\n\n

示例2:多维数组

\n\n

让我们增加难度,保存包含嵌套数据的数组——例如购物车中的商品列表:

\n\n
<?php\n$cart = [\n    ['id' => 101, 'name' => '《PHP高手之路》', 'price' => 1500, 'quantity' => 2],\n    ['id' => 102, 'name' => '《JSON大师》课程', 'price' => 3000, 'quantity' => 1],\n    ['id' => 103, 'name' => '证书', 'price' => 500, 'quantity' => 3]\n];\n\n// 比较字符串大小\n$serialized = serialize($cart);\n$json = json_encode($cart, JSON_UNESCAPED_UNICODE);\n\necho "Serialize: " . strlen($serialized) . " 字节\\n";\necho "JSON: " . strlen($json) . " 字节\\n";\n// 输出(近似值):\n// Serialize: 218 字节\n// JSON: 188 字节\n?>
\n\n

结论:JSON通常更紧凑,尤其对于大型数组。这在数据库存储或网络传输时至关重要。

\n\n

性能:哪个更快?

\n\n

速度是关键因素之一。让我们在10,000次迭代中进行测试:

\n\n
<?php\n$bigArray = [];\nfor ($i = 0; $i < 1000; $i++) {\n    $bigArray[] = [\n        'id' => $i,\n        'name' => '元素 #' . $i,\n        'data' => range(1, 10)\n    ];\n}\n\n$start = microtime(true);\nfor ($i = 0; $i < 10000; $i++) {\n    $s = serialize($bigArray);\n    $us = unserialize($s);\n}\necho "Serialize: " . (microtime(true) - $start) . " 秒\\n";\n\n$start = microtime(true);\nfor ($i = 0; $i < 10000; $i++) {\n    $j = json_encode($bigArray);\n    $uj = json_decode($j, true);\n}\necho "JSON: " . (microtime(true) - $start) . " 秒\\n";\n?>
\n\n

结果(PHP 8.2):

\n