PHP:json_encode vs serialize用于存储在MySQL数据库中?

时间:2011-03-18 12:06:44

标签: php json serialization

我在我的表的一个字段中存储了一些“非结构化”数据(一个键控数组),我现在正在使用serialize()/ unserialize()来从数组到字符串来回“转换”。 / p>

但是,在反序列化数据时,我偶尔会遇到错误。我相信这些错误的发生是因为我正在序列化的数组中的字符串中的Unicode数据,尽管有一些Unicode数据的记录可以正常工作。 (DB字段为UTF-8)

我想知道使用json_encode而不是序列化是否会产生影响/使其更具弹性。这对我来说测试并不简单,因为在我的开发环境中一切都运行良好,但在生产中,时不时(大约1%的记录)我收到错误。

是的,我知道我正在寻找一个解决这个问题的实际解释而只是盲目地尝试一些东西,我希望我能在不花太多时间的情况下摆脱它。

你认为使用json_encode而不是serialize会使这对“序列化错误”更具弹性吗?数据格式看起来对我来说更“宽容”......

更新:我得到的实际错误是:

 Notice: unserialize(): Error at offset 401 of 569 bytes in C:\blah.php on line 20

谢谢! 丹尼尔

8 个答案:

答案 0 :(得分:12)

JSON 有一个主要优势:

  • 与PHP之外的其他语言的兼容性。

PHP的 serialize 有一个主要优势:

  • 它专门用于存储基于PHP的数据 - 最值得注意的是,它可以存储序列化对象,类的实例,当字符串被反序列化时,它们将被重新安装到正确的类类型。

(是的,这些优势完全相反)


在您的情况下,当您存储的数据并非真正的结构时,两种格式都可以很好地工作。

你所遇到的编码问题本身不应该与序列化有关:只要所有(数据库,连接到数据库,PHP文件......)都是UTF-8,序列化也应该有效。

答案 1 :(得分:2)

FriendFeed的人们选择了使用JSON的类似解决方案。你应该查看他们的blog post

答案 2 :(得分:1)

如果问题是(并且我相信是)UTF-8编码,则json_encodeserialize之间没有区别。两者都会使字符编码保持不变。

您应该确保为句柄所有 UTF-8字符正确设置了数据库/连接,或者在插入数据库之前将整个记录编码为支持的编码。

另请注明“我收到错误”的含义。

答案 3 :(得分:1)

在PHP文档中找到了这个...

function mb_unserialize($serial_str) { 
    $out = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $serial_str ); 
    return unserialize($out); 
} 

我不是很了解它,但它有效地反序列化我之前无法反序列化的数据。现在转移到JSON,我将在几周后报告这是否解决了随机获取某些记录“损坏”的问题

答案 4 :(得分:1)

json_encode()转换非ASCII符号(例如,“Schrödinger”变为“Schr \ u00f6dinger”)但序列化()不会。

来源:https://www.toptal.com/php/10-most-common-mistakes-php-programmers-make#common-mistake-6--ignoring-unicodeutf-8-issues

要保持UTF-8字符不变,您可以使用PHP 5.4中的选项JSON_UNESCAPED_UNICODE。

来源:https://stackoverflow.com/a/804089/1438029

答案 5 :(得分:0)

作为设计决策,我选择存储JSON,因为它只能表示数据结构,而序列化则绑定到PHP数据对象签名。

我看到的优点是: *您被迫将数据存储与顶部的任何逻辑层分开。 *您独立于数据对象类的更改(例如,您要添加字段)。

答案 6 :(得分:0)

在进行此操作时,我将给出自己的看法,序列化和json_encode都适合将数据存储在DB中,但是对于那些寻找性能的人,我已经进行了测试并得到了这些结果,json_encode有点microsegunds序列化速度更快,我使用此脚本来计算差异时间。

$bounced =array();
for($i=count($bounced); $i<9999; ++$i)$bounced[$i]=$i;


$timeStart = microtime(true);
var_dump(serialize ($bounced));
unserialize(serialize ($bounced));
print timer_diff($timeStart) . " sec.\n";
$timeStart = microtime(true);
var_dump(json_encode ($bounced));
json_decode(json_encode ($bounced));
print timer_diff($timeStart) . " sec.\n";

function timer_diff($timeStart)
{
    return number_format(microtime(true) - $timeStart, 3);
}

答案 7 :(得分:0)

我认为除非您绝对需要保留php特定类型,否则json_encode()是在MySQL的单个字段中存储结构化数据的一种方式。原因如下:

https://dev.mysql.com/doc/refman/5.7/en/json.html

  

从MySQL 5.7.8开始,MySQL支持RFC 7159定义的本机JSON数据类型,该类型可有效访问JSON(JavaScript对象表示法)文档中的数据

如果使用支持新JSON数据类型的MySQL版本,则可以从该功能中受益。

需要考虑的另一个重要点是对这些JSON字符串执行更改的能力。假设您的URL存储在整个数据库的编码字符串中。曾经尝试将现有数据库迁移到新域名的Wordpress用户可能会对此表示同情。如果序列化了,它将破坏一切。如果是JSON,则只需使用REPLACE()运行查询,一切就可以了。示例:

$arr = ['url' => 'http://example.com'];
$ser = serialize($arr);
$jsn = json_encode($arr);

$ser = str_replace('http://','https://',$ser);
$jsn = str_replace('http://','https://',$jsn);

print_r(unserialize($ser));
PHP Notice:  unserialize(): Error at offset 39 of 43 bytes in /root/sandbox/encoding.php on line 10
print_r(json_decode($jsn,true));
  

数组   (       [url] => https://example.com   )