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