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实现:

  1. 调用栈:
    • 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定制:

  1. 调用栈:

    • 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对象
  2. 解析器生成工具:

    • re2c 0.16(用于词法分析)
    • Bison 3.0.4(用于语法分析)

3. 解析过程详解

解析流程

  1. php_json_yyparse (语法分析)

    • 定义:#define yyparse php_json_yyparse
    • 位置:ext/json/json_parser.tab.c:115
    • 关键代码:通过yylex获取词法单元
  2. php_json_yylex (词法分析)

    • 定义:#define yylex php_json_yylex
    • 调用php_json_scan进行实际扫描
  3. php_json_scan (扫描器)

    • 位置:ext/json/json_scanner.c
    • 功能:匹配并解析字符串(包括Unicode转义如\uXXXX、回车符等)

Unicode解析示例

解析\u003e的过程:

  1. 字符匹配流程:

    • 遇到\:跳转至yy175
    • 遇到u:跳转至yy177
    • 遇到0:跳转至yy179yy182
    • 遇到3:跳转至yy186
    • 遇到e:跳转至yy190
  2. 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(对应字符'>')
    
  3. 字符串处理:

    s->str_esc += 5;  // \u003e -> >
    size_t len = s->cursor - s->str_start - s->str_esc - 1 + s->utf8_invalid_count;
    

4. 代码分析方法

静态分析

  1. 关键文件:

    • ext/json/json.c
    • ext/json/json_parser.tab.c
    • ext/json/json_scanner.c
  2. 工具推荐:

    • Sublime Text 3 / Visual Studio Code
    • Understand(代码分析工具)
    • Lex/Flex/Yacc/Bison(解析器生成工具)

动态分析

  1. 关键断点:

    • php_json_scan
    • php_json_ucs2_to_int_ex
    • php_json_hex_to_int
  2. 调试技巧:

    • 优先使用单步调试而非单步跳过
    • 在关键函数处设置断点
    • 观察解析过程中的状态变化

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的重大改进:

  1. PHP 5使用基于JSON_checker的解析器
  2. PHP 7使用专为PHP定制的解析器,性能更好
  3. 解析过程分为词法分析(php_json_scan)和语法分析(php_json_yyparse)
  4. Unicode字符处理通过php_json_ucs2_to_int_ex等函数实现
  5. 可通过静态代码分析和动态调试深入理解解析过程

理解PHP的JSON解析机制有助于:

  • 更好地处理JSON数据
  • 调试JSON解析相关问题
  • 开发高性能的JSON处理应用
PHP JSON解析机制详解 1. PHP JSON解析基础 PHP通过 json_decode() 函数解析JSON字符串,其函数签名如下: 参数说明 | 参数 | 说明 | |------|------| | 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转换: 字符串处理: 4. 代码分析方法 静态分析 关键文件: ext/json/json.c ext/json/json_parser.tab.c ext/json/json_scanner.c 工具推荐: Sublime Text 3 / Visual Studio Code Understand(代码分析工具) Lex/Flex/Yacc/Bison(解析器生成工具) 动态分析 关键断点: php_json_scan php_json_ucs2_to_int_ex php_json_hex_to_int 调试技巧: 优先使用单步调试而非单步跳过 在关键函数处设置断点 观察解析过程中的状态变化 5. 实际应用示例 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处理应用