PHP是如何解析JSON的
字数 1891 2025-08-26 22:11:35
PHP JSON解析机制详解
1. PHP JSON解析基础
PHP通过json_decode()函数解析JSON字符串,其函数签名如下:
json_decode ( string $json [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] ) : mixed
参数说明
| 参数 | 说明 |
|---|---|
json |
待解码的JSON格式字符串(遵循RFC 7159标准) |
assoc |
为TRUE时返回数组而非对象 |
depth |
指定递归解析深度 |
options |
解码选项掩码 |
可用选项
JSON_BIGINT_AS_STRING:将大整数转为字符串(默认为float类型)JSON_OBJECT_AS_ARRAY:效果等同于将assoc设为TRUE
2. PHP版本实现差异
PHP 5实现
PHP 5.2.0开始内置JSON扩展,基于Douglas Crockford的JSON_checker实现:
- 调用栈:
zif_json_decode(ext/json/json.c:831-857)php_json_decode_ex(ext/json/json.c:680-796)json_utf8_to_utf16(UTF-8转UTF-16)new_JSON_parser(初始化)parse_JSON_ex(解析核心,位于ext/json/JSON_parser.c:439-750)
PHP 7实现
PHP 7使用全新解析器,专为PHP定制:
-
调用栈:
zif_json_decode(ext/json/json.c:312-362)- 默认嵌套深度:512
- 最大嵌套深度:2147483647
php_json_decode_ex(ext/json/json.c:246-264)- 初始化解析器:
php_json_parser_init - 解析JSON字符串:
php_json_yyparse - 错误处理:抛出异常及错误信息
- 返回PHP对象
- 初始化解析器:
-
解析器生成工具:
- re2c 0.16(用于词法分析)
- Bison 3.0.4(用于语法分析)
3. 解析过程详解
解析流程
-
php_json_yyparse(语法分析)- 定义:
#define yyparse php_json_yyparse - 位置:ext/json/json_parser.tab.c:115
- 关键代码:通过
yylex获取词法单元
- 定义:
-
php_json_yylex(词法分析)- 定义:
#define yylex php_json_yylex - 调用
php_json_scan进行实际扫描
- 定义:
-
php_json_scan(扫描器)- 位置:ext/json/json_scanner.c
- 功能:匹配并解析字符串(包括Unicode转义如
\uXXXX、回车符等)
Unicode解析示例
解析\u003e的过程:
-
字符匹配流程:
- 遇到
\:跳转至yy175 - 遇到
u:跳转至yy177 - 遇到
0:跳转至yy179和yy182 - 遇到
3:跳转至yy186 - 遇到
e:跳转至yy190
- 遇到
-
Unicode转换:
int utf16 = php_json_ucs2_to_int(s, 2); // 调用php_json_ucs2_to_int_ex return php_json_ucs2_to_int_ex(s, size, 1); // 返回62(对应字符'>') -
字符串处理:
s->str_esc += 5; // \u003e -> > size_t len = s->cursor - s->str_start - s->str_esc - 1 + s->utf8_invalid_count;
4. 代码分析方法
静态分析
-
关键文件:
ext/json/json.cext/json/json_parser.tab.cext/json/json_scanner.c
-
工具推荐:
- Sublime Text 3 / Visual Studio Code
- Understand(代码分析工具)
- Lex/Flex/Yacc/Bison(解析器生成工具)
动态分析
-
关键断点:
php_json_scanphp_json_ucs2_to_int_exphp_json_hex_to_int
-
调试技巧:
- 优先使用单步调试而非单步跳过
- 在关键函数处设置断点
- 观察解析过程中的状态变化
5. 实际应用示例
<?php
// Unicode转义示例
print_r("===== Unicode \\u003e ===== ");
$str = '{"vk":"vir\u003eink"}';
$obj = json_decode($str);
print_r($str . "\r\n");
print_r($obj);
/* 输出:
===== Unicode \u003e =====
{"vk":"vir\u003eink"}
stdClass Object
(
[vk] => vir>ink
)
*/
6. 总结
PHP的JSON解析机制经历了从PHP 5到PHP 7的重大改进:
- PHP 5使用基于JSON_checker的解析器
- PHP 7使用专为PHP定制的解析器,性能更好
- 解析过程分为词法分析(
php_json_scan)和语法分析(php_json_yyparse) - Unicode字符处理通过
php_json_ucs2_to_int_ex等函数实现 - 可通过静态代码分析和动态调试深入理解解析过程
理解PHP的JSON解析机制有助于:
- 更好地处理JSON数据
- 调试JSON解析相关问题
- 开发高性能的JSON处理应用