class JSON::Ext::Parser
这是以 C 扩展实现的 JSON 解析器。可以通过在 JSON 中设置 parser= 方法来配置使用它。
JSON.parser = JSON::Ext::Parser
在 JSON 中使用方法 parser= 来设置。
公共类方法
来源
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
GET_PARSER_INIT;
rb_check_arity(argc, 1, 2);
parser_init(json, argv[0], argc == 2 ? argv[1] : Qnil);
return self;
}
为字符串 source 创建一个新的 JSON::Ext::Parser 实例。
它将由 opts 哈希进行配置。opts 可以包含以下键
opts 可以包含以下键
-
max_nesting: 允许在解析的数据结构中嵌套的最大深度。可以使用 :max_nesting => false|nil|0 来禁用深度检查,默认为 100。
-
allow_nan: 如果设置为 true,则允许
Parser解析 RFC 4627 中禁止的 NaN、Infinity 和 -Infinity。此选项默认为 false。 -
symbolize_names: 如果设置为 true,则返回
JSON对象中的名称(键)的符号。否则,返回字符串,这也是默认值。此选项不能与 create_additions 选项同时使用。 -
create_additions: 如果设置为 false,即使找到匹配的类和 create_id,
Parser也不会创建附加项。此选项默认为 false。 -
object_class: 默认为
Hash。如果提供了其他类型,则将使用它来代替Hash来表示JSON对象。该类型必须响应不带参数的new,并返回一个响应[]=的对象。 -
array_class: 默认为
Array。如果提供了其他类型,则将使用它来代替Hash来表示JSON数组。该类型必须响应不带参数的new,并返回一个响应 +<<+ 的对象。 -
decimal_class: 指定要使用的类,而不是默认类。
(Float) when parsing decimal numbers. This class must accept a single string argument in its constructor.
来源
static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts)
{
char *p, *pe;
int cs = EVIL;
VALUE result = Qnil;
JSON_Parser _parser = {0};
JSON_Parser *json = &_parser;
parser_init(json, source, opts);
char stack_buffer[FBUFFER_STACK_SIZE];
fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE);
VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
rvalue_stack stack = {
.type = RVALUE_STACK_STACK_ALLOCATED,
.ptr = rvalue_stack_buffer,
.capa = RVALUE_STACK_INITIAL_CAPA,
};
json->stack = &stack;
#line 2957 "parser.c"
{
cs = JSON_start;
}
#line 1323 "parser.rl"
p = json->source;
pe = p + json->len;
#line 2966 "parser.c"
{
if ( p == pe )
goto _test_eof;
switch ( cs )
{
st1:
if ( ++p == pe )
goto _test_eof1;
case 1:
switch( (*p) ) {
case 13: goto st1;
case 32: goto st1;
case 34: goto tr2;
case 45: goto tr2;
case 47: goto st6;
case 73: goto tr2;
case 78: goto tr2;
case 91: goto tr2;
case 102: goto tr2;
case 110: goto tr2;
case 116: goto tr2;
case 123: goto tr2;
}
if ( (*p) > 10 ) {
if ( 48 <= (*p) && (*p) <= 57 )
goto tr2;
} else if ( (*p) >= 9 )
goto st1;
goto st0;
st0:
cs = 0;
goto _out;
tr2:
#line 1249 "parser.rl"
{
char *np = JSON_parse_value(json, p, pe, &result, 0);
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
}
goto st10;
st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
#line 3010 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
case 47: goto st2;
}
if ( 9 <= (*p) && (*p) <= 10 )
goto st10;
goto st0;
st2:
if ( ++p == pe )
goto _test_eof2;
case 2:
switch( (*p) ) {
case 42: goto st3;
case 47: goto st5;
}
goto st0;
st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
if ( (*p) == 42 )
goto st4;
goto st3;
st4:
if ( ++p == pe )
goto _test_eof4;
case 4:
switch( (*p) ) {
case 42: goto st4;
case 47: goto st10;
}
goto st3;
st5:
if ( ++p == pe )
goto _test_eof5;
case 5:
if ( (*p) == 10 )
goto st10;
goto st5;
st6:
if ( ++p == pe )
goto _test_eof6;
case 6:
switch( (*p) ) {
case 42: goto st7;
case 47: goto st9;
}
goto st0;
st7:
if ( ++p == pe )
goto _test_eof7;
case 7:
if ( (*p) == 42 )
goto st8;
goto st7;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
switch( (*p) ) {
case 42: goto st8;
case 47: goto st1;
}
goto st7;
st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
if ( (*p) == 10 )
goto st1;
goto st9;
}
_test_eof1: cs = 1; goto _test_eof;
_test_eof10: cs = 10; goto _test_eof;
_test_eof2: cs = 2; goto _test_eof;
_test_eof3: cs = 3; goto _test_eof;
_test_eof4: cs = 4; goto _test_eof;
_test_eof5: cs = 5; goto _test_eof;
_test_eof6: cs = 6; goto _test_eof;
_test_eof7: cs = 7; goto _test_eof;
_test_eof8: cs = 8; goto _test_eof;
_test_eof9: cs = 9; goto _test_eof;
_test_eof: {}
_out: {}
}
#line 1326 "parser.rl"
if (json->stack_handle) {
rvalue_stack_eagerly_release(json->stack_handle);
}
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
raise_parse_error("unexpected token at '%s'", p);
return Qnil;
}
}
公共实例方法
来源
static VALUE cParser_parse(VALUE self)
{
char *p, *pe;
int cs = EVIL;
VALUE result = Qnil;
GET_PARSER;
char stack_buffer[FBUFFER_STACK_SIZE];
fbuffer_stack_init(&json->fbuffer, FBUFFER_INITIAL_LENGTH_DEFAULT, stack_buffer, FBUFFER_STACK_SIZE);
VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
rvalue_stack stack = {
.type = RVALUE_STACK_STACK_ALLOCATED,
.ptr = rvalue_stack_buffer,
.capa = RVALUE_STACK_INITIAL_CAPA,
};
json->stack = &stack;
#line 2779 "parser.c"
{
cs = JSON_start;
}
#line 1285 "parser.rl"
p = json->source;
pe = p + json->len;
#line 2788 "parser.c"
{
if ( p == pe )
goto _test_eof;
switch ( cs )
{
st1:
if ( ++p == pe )
goto _test_eof1;
case 1:
switch( (*p) ) {
case 13: goto st1;
case 32: goto st1;
case 34: goto tr2;
case 45: goto tr2;
case 47: goto st6;
case 73: goto tr2;
case 78: goto tr2;
case 91: goto tr2;
case 102: goto tr2;
case 110: goto tr2;
case 116: goto tr2;
case 123: goto tr2;
}
if ( (*p) > 10 ) {
if ( 48 <= (*p) && (*p) <= 57 )
goto tr2;
} else if ( (*p) >= 9 )
goto st1;
goto st0;
st0:
cs = 0;
goto _out;
tr2:
#line 1249 "parser.rl"
{
char *np = JSON_parse_value(json, p, pe, &result, 0);
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
}
goto st10;
st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
#line 2832 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
case 47: goto st2;
}
if ( 9 <= (*p) && (*p) <= 10 )
goto st10;
goto st0;
st2:
if ( ++p == pe )
goto _test_eof2;
case 2:
switch( (*p) ) {
case 42: goto st3;
case 47: goto st5;
}
goto st0;
st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
if ( (*p) == 42 )
goto st4;
goto st3;
st4:
if ( ++p == pe )
goto _test_eof4;
case 4:
switch( (*p) ) {
case 42: goto st4;
case 47: goto st10;
}
goto st3;
st5:
if ( ++p == pe )
goto _test_eof5;
case 5:
if ( (*p) == 10 )
goto st10;
goto st5;
st6:
if ( ++p == pe )
goto _test_eof6;
case 6:
switch( (*p) ) {
case 42: goto st7;
case 47: goto st9;
}
goto st0;
st7:
if ( ++p == pe )
goto _test_eof7;
case 7:
if ( (*p) == 42 )
goto st8;
goto st7;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
switch( (*p) ) {
case 42: goto st8;
case 47: goto st1;
}
goto st7;
st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
if ( (*p) == 10 )
goto st1;
goto st9;
}
_test_eof1: cs = 1; goto _test_eof;
_test_eof10: cs = 10; goto _test_eof;
_test_eof2: cs = 2; goto _test_eof;
_test_eof3: cs = 3; goto _test_eof;
_test_eof4: cs = 4; goto _test_eof;
_test_eof5: cs = 5; goto _test_eof;
_test_eof6: cs = 6; goto _test_eof;
_test_eof7: cs = 7; goto _test_eof;
_test_eof8: cs = 8; goto _test_eof;
_test_eof9: cs = 9; goto _test_eof;
_test_eof: {}
_out: {}
}
#line 1288 "parser.rl"
if (json->stack_handle) {
rvalue_stack_eagerly_release(json->stack_handle);
}
if (cs >= JSON_first_final && p == pe) {
return result;
} else {
raise_parse_error("unexpected token at '%s'", p);
return Qnil;
}
}
解析当前的 JSON 文本 source,并返回完整的数据结构作为结果。如果解析失败,则会引发 JSON::ParserError 异常。