PHP中遇到BOM、<feff>编码导致json_decode函数无法解析问题

yipeiwu_com5年前PHP代码库

昨天同事遇到一个奇怪的问题,就是以下代码,无法通过JSON校验,也无法通过PHP的json_decode函数解析。

复制代码 代码如下:

[
    {
        "title": "",
        "pinyin": ""
    }
]

可能聪明的你已经猜到其中包含有不看见的特殊字符,在vim下查看:
复制代码 代码如下:

[
    {
        <feff>"title": "",
        "pinyin": ""
    }
]

发现在“title”前面有一个字符<feff>,如果你之前了解过BOM,应该知道这个特殊字符就是BOM,关于其介绍可以参考另一篇文章:计算机中的字符串编码、乱码、BOM等问题详解.


在Linux下通过xxd命令查看文件内容的十六进制:

复制代码 代码如下:

0000000: 5b 0a 20 20 20 20 7b 0a 20 20 20 20 20 20 20 20  [.    {.       
0000010: ef bb bf 22 74 69 74 6c 65 22 3a 20 22 22 2c 0a  ..."title": "",.
0000020: 20 20 20 20 20 20 20 20 22 70 69 6e 79 69 6e 22          "pinyin"
0000030: 3a 20 22 22 0a 20 20 20 20 7d 0a 5d 0a           : "".    }.].

可以看到刚才那个"title"前面的特殊字符十六进制为:ef bb bf,正是标记UTF-8的BOM。BOM的含义如下:
复制代码 代码如下:

开头字节            Charset/encoding
EF BB BF        UTF-8
FE FF           UTF-16/UCS-2, little endian(UTF-16LE)
FF FE           UTF-16/UCS-2, big endian(UTF-16BE)
FF FE 00 00     UTF-32/UCS-4, little endian.
00 00 FE FF     UTF-32/UCS-4, big-endia

发现问题解决就很容易了,查找删除BOM就OK了,linux下BOM相关的命令有:

VIM的BOM操作

复制代码 代码如下:

#添加BOM
:set bomb
#删除BOM
:set nobomb
#查询BOM
:set bomb?

查找UTF-8编码中的BOM

复制代码 代码如下:
grep -I -r -l $'\xEF\xBB\xBF' /path

还可以在svn的钩子中禁止提交BOM(以下代码来自网络,没校验)
复制代码 代码如下:

#!/bin/sh

REPOS="$1"
TXN="$2"

SVNLOOK=/usr/bin/svnlook

FILES=`$SVNLOOK changed -t "$TXN" "$REPOS" | awk {'print $2'}`

for FILE in $FILES; do
    CONTENT=`$SVNLOOK cat -t "$TXN" "$REPOS" "$FILE"`

    if echo $CONTENT | head -c 3 | xxd -i | grep -q '0xef, 0xbb, 0xbf'; then
        echo "BOM!" 1>&2
        exit 1
    fi
done


最后提醒大家在wowdows下最好别使用记事本等会自动添加BOM的编辑器修改代码,容易引发一些问题。

相关文章

php简单对象与数组的转换函数代码(php多层数组和对象的转换)

复制代码 代码如下: function arrayToObject($e){ if( gettype($e)!='array' ) return; foreach($e as $k=&g...

PHP编程计算日期间隔天数的方法

本文实例讲述了PHP编程计算日期间隔天数的方法。分享给大家供大家参考,具体如下: 刚开始在没有查PHP手册的情况下,用比较老套方法也折腾出来了,代码是这样子实现的: $date_1...

php实现的数组转xml案例分析

本文实例讲述了php实现的数组转xml。分享给大家供大家参考,具体如下: 0x00 需求 最近要做百度、360、神马搜索的网站sitemap,三家的格式都是xml,然而具体的细节还有有差...

php park、unpark、ord 函数使用方法(二进制流接口应用实例)

php park、unpark、ord 函数使用方法(二进制流接口应用实例)

park,unpark,ord这3个函数,在我们工作中,用到它们的估计不多。 我在最近一个工作中,因为通讯需要用到二进制流,然后接口用php接收。当时在处理时候,查阅不少资料。因为它们使...

关于php几种字符串连接的效率比较(详解)

php大致有三种字符串连接: 1、直接用.来进行连接。 2、用.=进行连接。 3、先压入数组,再通过join函数连接。 下面分别对这三种方法的效率进行测试: 第一种方法代码如下: &...