开发过程中经常碰到要把前端的json格式的数据传递到后端php,php做一些业务处理后把数据存到mysql,然后,php再从mysql中取出数据返回到前端。虽然这是一个再基础不过的处理过程,但还是有不少问题需要认真研究。下面从几个环节看看可能出现的各种问题。
存入mysql前
假设前端传入的数据是:
{"html":"a"b"}
json_decode后,PHP对象是:
object(stdClass)#3 (1) {
["html"]=>
string(3) "a"b"
}
注意要处理的数据中包含了双引号,这个字符在json中需要转意,在mysql中也需要转意。假如要把这个对象转换为json串存入mysql,先用json_encode处理:
{"html":"a\"b"}
注意:双引号前面加上了反斜杠。再用real_escape_string处理:
{\"html\":\"a\\\"b\"}
注意:所有的双引号和反斜杠(json_encode加上的那个)都加上了反斜杠。存入数据库的内容:
{"html":"a\"b"}
按照这样的过程处理数据是正常的,从数据库取出后,用json_decode可以恢复原来的数据。但是如果在存入数据库前没有做real_escape_string的处理,直接存入数据库,那么数据库的内容:
{"html":"a"b"}
注意:这时a和b之间的双引号前面的反斜杠被mysql去掉了,数据库中的内容已经不是合法的json串。
结论1:把json存入mysql数据库前必须做1次real_escape_string
处理中文
json_encode处理包含中文的字符串时,会将中文字符转换为unicode的形式(uXXXX),而且通过json_decode是不能恢复的。例如处理前的对象是:
object(stdClass)#3 (1) {
["html"]=>
string(6) "你好"
}
json_encode后的json串是:
{"html":"\u4f60\u597d"}
real_escape_string处理后存入mysql数据库:
{"html":"\u4f60\u597d"}
这样带来的问题是在mysql中就无法直接对这个串做处理,例如:
like '%你%'
解决这个问题的方法是,在进行json_encode前先对要处理的对象的值用urlencode处理一遍,json_encode后再用urldecode恢复回来,这样的到json串是:
{"html":"你好"}
结论2:通过urlencode解决json_encode将中文字符编码为unicode的形式。
处理特殊字符
通过urlencode解决中文问题会带来新问题,json的特殊字符处理。例如:双引号会被编码为“%22”,json_encode不会对%22特殊处理,【你"好】本应该编码为【你\"好】,对双引号进行转义,但是结果是【你"好】,已经不是一个合法的json字符串。
解决这个问题前首先要搞清楚json中有哪些特殊字符,看下图:
来自:http://www.json.org/
解决这个问题的思路是在进行urlencode之前,先在这些特殊字符前加上反斜杠,这样urldecode之后就有了转义的反斜杠。
$str = str_replace(array("\\", '"', "\n", "\r", "\t"), array("\\\\", '\"', "\\n", "\\r", "\\t"), $str);
执行这个操作时要注意,必须先替换反斜杠,再替换其它特殊字符,否则,给特殊字符添加的反斜杠又会被再加上反斜杠。另一个问题注意要用双引号,php中单引号的内容不会转义,双引号才会。
总结:通过上述3个方面的处理,应该可以正确的处理json的问题了。但是,也许应该直接写一个拼接json串的方法,彻底不用json_encode,这样效率更高些,以后有机会试试。