PHP中遇到BOM、编码导致json_decode函数无法解析问题
昨天同事遇到一个奇怪的问题,就是以下代码,无法通过JSON校验,也无法通过PHP的json_decode函数解析。
[ { "title":"", "pinyin":"" } ]
可能聪明的你已经猜到其中包含有不看见的特殊字符,在vim下查看:
[ { <feff>"title":"", "pinyin":"" } ]
发现在“title”前面有一个字符<feff>,如果你之前了解过BOM,应该知道这个特殊字符就是BOM,关于其介绍可以参考另一篇文章:计算机中的字符串编码、乱码、BOM等问题详解.
在Linux下通过xxd命令查看文件内容的十六进制:
0000000:5b0a202020207b0a2020202020202020 [. {. 0000010:efbbbf227469746c65223a2022222c0a ..."title":"",. 0000020:20202020202020202270696e79696e22 "pinyin" 0000030:3a2022220a202020207d0a5d0a :"". }.].
可以看到刚才那个"title"前面的特殊字符十六进制为:efbbbf,正是标记UTF-8的BOM。BOM的含义如下:
开头字节 Charset/encoding EFBBBF UTF-8 FEFF UTF-16/UCS-2,littleendian(UTF-16LE) FFFE UTF-16/UCS-2,bigendian(UTF-16BE) FFFE0000 UTF-32/UCS-4,littleendian. 0000FEFF UTF-32/UCS-4,big-endia
发现问题解决就很容易了,查找删除BOM就OK了,linux下BOM相关的命令有:
VIM的BOM操作
#添加BOM :setbomb #删除BOM :setnobomb #查询BOM :setbomb?
查找UTF-8编码中的BOM
grep-I-r-l$'\xEF\xBB\xBF'/path
还可以在svn的钩子中禁止提交BOM(以下代码来自网络,没校验)
#!/bin/sh
REPOS="$1" TXN="$2"
SVNLOOK=/usr/bin/svnlook
FILES=`$SVNLOOKchanged-t"$TXN""$REPOS"|awk{'print$2'}`
forFILEin$FILES;do CONTENT=`$SVNLOOKcat-t"$TXN""$REPOS""$FILE"`
ifecho$CONTENT|head-c3|xxd-i|grep-q'0xef,0xbb,0xbf';then echo"BOM!"1>&2 exit1 fi done