class JSON::Ext::Parser

这是作为 C 扩展实现的 JSON 解析器。可以通过在 JSON 中使用方法 parser= 来配置使用它。

JSON.parser = JSON::Ext::Parser

用方法 parser= 在 JSON 中配置。

公共类方法

new(source, opts → {}) 点击切换源

为字符串 source 创建一个新的 JSON::Ext::Parser 实例。

它将由 opts 哈希配置。opts 可以有以下键

opts 可以有以下键

  • max_nesting:解析的数据结构中允许的最大嵌套深度。使用 :max_nesting => false|nil|0 禁用深度检查,默认为 100。

  • allow_nan:如果设置为 true,则允许 Parser 解析 NaN、Infinity 和 -Infinity,这与 RFC 4627 相悖。此选项默认为 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_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;
}
parse(p1, p2) 点击切换源
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;
    }
}

公共实例方法

parse() 点击切换源

解析当前的 JSON 文本 source 并返回完整的数据结构作为结果。如果解析失败,则引发 JSON::ParserError

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;
    }
}
source() 点击切换源

返回用于构造此 Parser 的当前 source 字符串的副本。

static VALUE cParser_source(VALUE self)
{
    GET_PARSER;
    return rb_str_dup(json->Vsource);
}