php怎么解析json,PHP是如何解析JSON的

Info

json_decode ( string $json [, bool $assoc = false [, int $depth = 512 [, int $options = 0 ]]] ) : mixed

(PHP 5 >= 5.2.0, PHP 7, PECL json >= 1.2.0)

json_decode — 对 JSON 格式的字符串进行解码

参数

说明

json

待解码的 json string 格式的字符串。(RFC 7159)

assoc

当该参数为 TRUE 时,将返回 array 而非 object。

depth

指定递归深度。

options

JSON解码的掩码选项。 现在有两个支持的选项。

JSON_BIGINT_AS_STRING,大整数转为字符串(默认float类型)。

JSON_OBJECT_AS_ARRAY,与将assoc设置为 TRUE 有相同的效果。

变化

自 PHP 5.2.0 起,JSON 扩展默认内置并编译进了 PHP。

PHP 5 JSON_checker - Douglas Crockford

a Pushdown Automaton that very quickly determines.

PHP 7 中是改进的全新解析器,专门为 PHP 订制,软件许可证为 PHP license。

re2c 0.16

Bison 3.0.4

PHP 版本说明

PHP 5 : Call Stack of json_decode (zif_json_decode)

毕竟5已经停止更新了,就简单提及一下

zif_json_decode ext/json/json.c:831-857

php_json_decode_ex ext/json/json.c:680-796

json_utf8_to_utf16 utf8 转 utf16

new_JSON_parser 初始化

parse_JSON_ex 解析 ext/json/JSON_parser.c:439-750

JSON_parser.c 就是 JSON_checker 的

PHP 7 : Call Stack of json_decode (zif_json_decode)

zif_json_decode

ext/json/json.c:312-362

默认嵌套深度 :depth = PHP_JSON_PARSER_DEFAULT_DEPTH (= 512 [php_json.h])

最大嵌套深度 :depth > INT_MAX (= 2147483647 [php.h])

接受参数并调用php_json_decode_ex

php_json_decode_ex

ext/json/json.c:246-264

初始化 PHP 的json解析器 php_json_parser_init

解析 json 字符串 php_json_yyparse

如果解析错误,抛出异常及错误信息

返回 PHP Object

php_json_yyparse (yyparse)

ext/json/json_parser.tab.c:115

#define yyparse php_json_yyparse

ext/json/json_parser.tab.c:1194-843

int yyparse(php_json_parser *parser)

// L:1359

if (yychar == YYEMPTY)

{

YYDPRINTF((stderr, "Reading a token: "));

yychar = yylex(&yylval, parser);

}

yylex (php_json_yylex)

ext/json/json_parser.tab.c:116

#define yylex php_json_yylex

ext/json/json_parser.tab.c:1899-1904

static int php_json_yylex(union YYSTYPE *value, php_json_parser *parser)

{

int token = php_json_scan(&parser->scanner);

value->value = parser->scanner.value;

return token;

}

php_json_scan

ext/json/json_scanner.c:106-end

匹配并解析字符串(包括\uXXXX,\r等)

Flowchart

701c2100da9ee28e4620c9abae29b356.png

Example Parser Unicode(\u003e)

Source Code json.php

print_r("===== Unicode\\u003e ===== ");

$str = '{"vk":"vir\u003eink"}';

$obj = json_decode($str);

print_r($str . "\r\n");

print_r($obj);

/* Output

===== Unicode \u003e =====

{"vk":"vir\u003eink"}

stdClass Object

(

[vk] => vir>ink

)

*/

Call Stack

进入解析

php_json_scan (ext/json/json_scanner.c)

JSON字符 匹配 value "\u003e"

省略 vir...

if (yych <= '\\') goto yy77; (L:553) // \

if (yych <= 'u') goto yy90; (L:625) // u

if (yych <= '0') goto yy94; (L:706) // 0

if (yych <= '0') goto yy97; (L:747) // 0

if (yych <= '7') goto yy102; (L:797) // 3

if (yych <= 'f') goto yy107; (L:863) // e

s->str_esc += 5; (L:917) // \u003e -> >

size_t len = s->cursor - s->str_start - s->str_esc - 1 + s->utf8_invalid_count; (L:583) // 长度处理

省略ink

b42b6e3798068c039ba4ebf56080f2ea.png

Unicode匹配并解析(\u003e)

if (yych == '\\') goto yy175; (L:1369) // \

if (yych == 'u') goto yy177; (L:1381) // u

if (yych <= '0') goto yy179; (L:1420) // 0

if (yych <= '0') goto yy182; (L:1443) // 0

if (yych <= '7') goto yy186; (L:1485) // 3

if (yych <= 'f') goto yy190; (L:1539) // e

转换 Unicode 为 Char

int utf16 = php_json_ucs2_to_int(s, 2); (L:1581->92)

return php_json_ucs2_to_int_ex(s, size, 1); (L:94) // return 62

1a0556281f21fbf2a1fc5d1c89319e03.png

从静态到动态

静态分析

代码阅读工具

Sublime Text 3

Visual Studio Code

ext: Lex Flex Yacc Bison

Understand

分析

目标 : JSON 扩展

目录 : ext/json/

文件 : ext/json/json.c

函数 : static PHP_FUNCTION(json_decode)

函数名称都比较容易看懂,编辑器大多数都有转到定义功能

php_json_decode_ex

php_json_parser_init

php_json_yyparse

...etc

上文(PHP 7 : Call Stack of json_decode )列的也比较详细了

一个字就是看

ext/json/README也是要先看看的

The parser is implemented using re2c and Bison. The used versions

of both tools for generating files in the repository are following:

re2c 0.16

Bison 3.0.4

当然,后缀为*.y和*.re的文件也说明了这个解析涉及扫描程序(scanner)和语法分析(parser)。

PS. 编译原理。。。反正我不懂

动态分析

通过静态分析,我们可以得到一些关键函数

php_json_decode_ex

php_json_yyparse

yylex

php_json_scan

给php_json_scan下断点,单步进入一把唆,调试过程中随时加断点

php_json_scan

std: (ext/json/json_parser.tab.c:115)

yyc_JS: (ext/json/json_parser.tab.c:167)

yyc_STR_P1: (ext/json/json_parser.tab.c:547)

php_json_ucs2_to_int_ex

php_json_hex_to_int

PS. 单步跳过有点坑,尽可能用单步调试和单步跳出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值