PHP和JSON那点事

起因

最近在做一个项目,用PHP给客户端提供API接口。客户端通过HTTP请求得到如下数据,然后JSON编码后返回。

$arr = [
    [
        'id'    => 1,
        'name'  => 'jack',
        'hobby' => [],
    ],
    [
        'id'    => 2,
        'name'  => 'rose',
        'hobby' => [
            'childhood'=>[
                'draw'
            ],
            'adult'=>[
                'travel'
            ],
        ],
    ],
];
echo json_encode($arr);

//JSON编码后的数据
[
    {
        "id": 1,
        "name": "jack",
        "hobby": []
    },
    {
        "id": 2,
        "name": "rose",
        "hobby": {
            "childhood": [
                "draw"
            ],
            "adult": [
                "travel"
            ]
        }
    }
]

以上数据的「hobby」值在无数据时为数组类型,有数据时为对象类型。如果对接的是PHP这种弱类型语言,在处理时不会有任何问题,直接foreach循环就好。但是对接的是Android和Swift等强类型编程语言,一但指定了「hobby」值的数据类型,就不能更改,否则就会报错。

解决办法

旨在保证「hobby」值的类型在有数据和无数据时统一。

  • 方式1:强转数组为对象
{
    "id": 1,
    "name": "jack",
        "hobby": (object)[]
},
  • 方式2:JSON_FORCE_OBJECT
...
echo json_encode($arr,JSON_FORCE_OBJECT)//第二个参数为强转对象。

虽然问题解决了,但是产生了疑问:「为什么无数据时是数组类型,有数据时是对象类型」?通过阅读PHP官网,我找到了答案,并且发现一些有意思的事,做以下总结。

PHP处理JSON的函数

json_encode($1, $2, $3) - 对变量进行JSON编码

接收三个参数:

$1.除resource类型外所有变量类型,如为字符串类型编码必须是UTF-8。

$2.设置编码的方式,多个用「|」隔开

参数 说明
JSON_HEX_QUOT 双引号转16进制
JSON_HEX_TAG 标签转16进制
JSON_HEX_AMP &号转16进制
JSON_HEX_APOS 单引号转16进制
JSON_NUMERIC_CHECK 数字类型检测
JSON_PRETTY_PRINT 格式化打印
JSON_UNESCAPED_SLASHES 不转义「/」
JSON_FORCE_OBJECT 强转对象
JSON_PRESERVE_ZERO_FRACTION 保留小数点后的「0」
JSON_UNESCAPED_UNICODE 不转义unicode编码
JSON_PARTIAL_OUTPUT_ON_ERROR 有错误时部分展示

$3.最大深度,大于0

那么到底什么时候是数组,什么时候是对象?以下代码可以很好的解释,就不过多地阐述了。

echo "连续数组".PHP_EOL;
$sequential = array("foo", "bar", "baz", "blong");
echo json_encode($sequential,JSON_PRETTY_PRINT);

//output:
连续数组
[
    "foo",
    "bar",
    "baz",
    "blong"
]


echo PHP_EOL."非连续数组".PHP_EOL;
$nonsequential = array(1=>"foo", 2=>"bar", 3=>"baz", 4=>"blong");
echo json_encode($nonsequential,JSON_PRETTY_PRINT);


//output:
非连续数组
{
    "1": "foo",
    "2": "bar",
    "3": "baz",
    "4": "blong"
}


echo PHP_EOL."删除一个连续数组值的方式产生的非连续数组".PHP_EOL;
unset($sequential[1]);
echo json_encode($sequential,JSON_PRETTY_PRINT);


//output:
删除一个连续数组值的方式产生的非连续数组
{
    "0": "foo",
    "2": "baz",
    "3": "blong"
}

json_decode($1, $2, $3, $4) - 对JSON格式的字符串进行解码

$1:待解码JSON字符串类型的数据且必须为UTF-8编码

$2:true返回数组,否则返回对象

$3:指定递归深度

$4:设置解码方式

参数 说明
JSON_BIGINT_AS_STRING 大整数转为字符串而非默认的float类型
JSON_OBJECT_AS_ARRAY true时,跟$2为true时相同效果

json_last_error_msg() - 返回JSON编码或解码时错误消息

json_last_error() - 返回最后发生的错误ID

从官网上看到一个实用函数:判断是否是有效的JSON

 function json_validate($string) {
        if (is_string($string)) {
            @json_decode($string);
            return (json_last_error() === JSON_ERROR_NONE);
        }
        return false;
    }

参考:

http://php.net/
http://php.net/manual/zh/function.json-last-error.php#114264

posted @ 2021-07-09 16:24  luyuqiang  阅读(59)  评论(0编辑  收藏  举报