PHP JSON 编解码入门:json_encode 与 json_decode

现在前后端交互、调第三方接口、写配置文件,几乎都离不开 JSON。PHP 内置了两个函数搞定一切:json_encode() 把 PHP 数据转成 JSON 字符串,json_decode() 把 JSON 字符串转回 PHP 数据。这篇把日常最常用的用法整理一遍。

json_encode:数组变 JSON

<?php
$user = [
    'name' => '小明',
    'age' => 18,
    'hobby' => ['篮球', '编程'],
];
echo json_encode($user);
// 输出:{"name":"\u5c0f\u660e","age":18,"hobby":["\u7bee\u7403","\u7f16\u7a0b"]}

能跑,但中文变成了 \u5c0f\u660e 这样的转义。虽然语法上合法,接口返回中文时一般都希望保留原文。

中文不转义:JSON_UNESCAPED_UNICODE

加上这个选项,中文原样输出:

<?php
$user = ['name' => '小明', 'age' => 18];
echo json_encode($user, JSON_UNESCAPED_UNICODE);
// 输出:{"name":"小明","age":18}

调试时想打印得好看一点,再叠加 JSON_PRETTY_PRINT(选项用 | 组合):

<?php
$user = ['name' => '小明', 'age' => 18];
echo json_encode($user, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
// 输出(带缩进和换行):
// {
//     "name": "小明",
//     "age": 18
// }

json_decode:JSON 变回 PHP

默认解码成对象(stdClass):

<?php
$json = '{"name":"小明","age":18}';
$obj = json_decode($json);
echo $obj->name;
// 输出:小明

第二个参数传 true,就解码成关联数组,用方括号访问:

<?php
$json = '{"name":"小明","age":18}';
$arr = json_decode($json, true);
echo $arr['name'];
// 输出:小明
echo $arr['age'] + 10;
// 输出:28

团队里更常见的是统一用数组形式,嵌套结构访问起来更顺手。

嵌套结构怎么取值

JSON 经常一层套一层,解码后按对应结构往下取就行:

<?php
$json = '{"class":"三班","students":[{"name":"小明","score":92},{"name":"小红","score":88}]}';
$data = json_decode($json, true);
echo $data['class'];
// 输出:三班
echo $data['students'][0]['name'];
// 输出:小明
echo $data['students'][1]['score'];
// 输出:88

解码失败怎么办

JSON 不合法时 json_decode() 返回 null,但 null 也可能是正常值,所以要用 json_last_error() 确认到底是不是出错了:

<?php
$bad = '{"name": "小明",}';
$data = json_decode($bad, true);
if (json_last_error() !== JSON_ERROR_NONE) {
    echo 'JSON 解析失败';
    // 输出:JSON 解析失败(末尾多了个逗号,不合法)
} else {
    var_dump($data);
}

写接口时这个检查很有必要,能避免拿着 null 往下跑出一串莫名的错误。

小结

记住两组搭配就够了:输出给前端用 json_encode($data, JSON_UNESCAPED_UNICODE),中文不乱码;接收外部 JSON 用 json_decode($str, true) 解码成数组,配合 json_last_error() 做合法性检查。剩下的美化输出、选项组合,用到了查一下手册即可。