Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add an optional create additions callback #182

Open
wants to merge 2 commits into from

1 participant

Mo Morsi
Mo Morsi

Follow up to workarounds describe in issue #179.

If not set create_additions still implements current behaviour.

If set to a proc this will be invoked in lieu of deep const get to evaluate the json class string and return a ruby class. It is up to the developer to specify the implementation details of this mapping.

Putting this out there for comments and hopeful merger into the codebase.

movitto added some commits
Mo Morsi movitto Expand create_additions to take optional callback
If specified json will pass the string json_class
and use the value returned as the ruby class to
instantiate
3a0ee17
Mo Morsi movitto update autogenerated files 6dd716c
Mo Morsi

Hey just updated the patches to work on travis. Wasn't anything major, just had the wrong types for create_additions in the extensions. The builds that are failing are the allowed failures for rubinius as well as the latest ruby head (which looks to be a ruby issue as it's not even getting to installing the deps nevermind testing json itself). I'm assuming travis integration is acceptable at this point.

If there is anything else that needs TBD just shout out, would love to see this make it in so I don't have to implement one of the workarounds in rjr.

Thanks.

Mo Morsi movitto referenced this pull request in movitto/rjr
Closed

Poor handle_message performance #15

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 21, 2013
  1. Mo Morsi

    Expand create_additions to take optional callback

    movitto authored
    If specified json will pass the string json_class
    and use the value returned as the ruby class to
    instantiate
  2. Mo Morsi

    update autogenerated files

    movitto authored
This page is out of date. Refresh to see the latest.
155 ext/json/ext/parser/parser.c
View
@@ -81,7 +81,7 @@ static VALUE CNaN, CInfinity, CMinusInfinity;
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
- i_match_string, i_aset, i_aref, i_leftshift;
+ i_match_string, i_aset, i_aref, i_leftshift, i_call;
#line 110 "parser.rl"
@@ -452,7 +452,12 @@ case 26:
klassname = rb_funcall(*result, i_aref, 1, json->create_id);
}
if (!NIL_P(klassname)) {
- VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
+ VALUE klass = NULL;
+ if(rb_class_of(json->create_additions) == rb_cProc)
+ klass = rb_funcall(json->create_additions, i_call, 1, klassname);
+ else
+ klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
+
if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
*result = rb_funcall(klass, i_json_create, 1, *result);
}
@@ -466,7 +471,7 @@ case 26:
-#line 470 "parser.c"
+#line 475 "parser.c"
static const int JSON_value_start = 1;
static const int JSON_value_first_final = 21;
static const int JSON_value_error = 0;
@@ -474,7 +479,7 @@ static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 271 "parser.rl"
+#line 276 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -482,14 +487,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 486 "parser.c"
+#line 491 "parser.c"
{
cs = JSON_value_start;
}
-#line 278 "parser.rl"
+#line 283 "parser.rl"
-#line 493 "parser.c"
+#line 498 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -514,14 +519,14 @@ case 1:
cs = 0;
goto _out;
tr0:
-#line 219 "parser.rl"
+#line 224 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
if (np == NULL) { p--; {p++; cs = 21; goto _out;} } else {p = (( np))-1;}
}
goto st21;
tr2:
-#line 224 "parser.rl"
+#line 229 "parser.rl"
{
char *np;
if(pe > p + 9 - json->quirks_mode && !strncmp(MinusInfinity, p, 9)) {
@@ -541,7 +546,7 @@ cs = 0;
}
goto st21;
tr5:
-#line 242 "parser.rl"
+#line 247 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -551,7 +556,7 @@ cs = 0;
}
goto st21;
tr9:
-#line 250 "parser.rl"
+#line 255 "parser.rl"
{
char *np;
json->current_nesting++;
@@ -561,7 +566,7 @@ cs = 0;
}
goto st21;
tr16:
-#line 212 "parser.rl"
+#line 217 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
@@ -571,7 +576,7 @@ cs = 0;
}
goto st21;
tr18:
-#line 205 "parser.rl"
+#line 210 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
@@ -581,19 +586,19 @@ cs = 0;
}
goto st21;
tr22:
-#line 199 "parser.rl"
+#line 204 "parser.rl"
{
*result = Qfalse;
}
goto st21;
tr25:
-#line 196 "parser.rl"
+#line 201 "parser.rl"
{
*result = Qnil;
}
goto st21;
tr28:
-#line 202 "parser.rl"
+#line 207 "parser.rl"
{
*result = Qtrue;
}
@@ -602,9 +607,9 @@ cs = 0;
if ( ++p == pe )
goto _test_eof21;
case 21:
-#line 258 "parser.rl"
+#line 263 "parser.rl"
{ p--; {p++; cs = 21; goto _out;} }
-#line 608 "parser.c"
+#line 613 "parser.c"
goto st0;
st2:
if ( ++p == pe )
@@ -765,7 +770,7 @@ case 20:
_out: {}
}
-#line 279 "parser.rl"
+#line 284 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -775,7 +780,7 @@ case 20:
}
-#line 779 "parser.c"
+#line 784 "parser.c"
static const int JSON_integer_start = 1;
static const int JSON_integer_first_final = 3;
static const int JSON_integer_error = 0;
@@ -783,7 +788,7 @@ static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 295 "parser.rl"
+#line 300 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -791,15 +796,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 795 "parser.c"
+#line 800 "parser.c"
{
cs = JSON_integer_start;
}
-#line 302 "parser.rl"
+#line 307 "parser.rl"
json->memo = p;
-#line 803 "parser.c"
+#line 808 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -833,14 +838,14 @@ case 3:
goto st0;
goto tr4;
tr4:
-#line 292 "parser.rl"
+#line 297 "parser.rl"
{ p--; {p++; cs = 4; goto _out;} }
goto st4;
st4:
if ( ++p == pe )
goto _test_eof4;
case 4:
-#line 844 "parser.c"
+#line 849 "parser.c"
goto st0;
st5:
if ( ++p == pe )
@@ -859,7 +864,7 @@ case 5:
_out: {}
}
-#line 304 "parser.rl"
+#line 309 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -874,7 +879,7 @@ case 5:
}
-#line 878 "parser.c"
+#line 883 "parser.c"
static const int JSON_float_start = 1;
static const int JSON_float_first_final = 8;
static const int JSON_float_error = 0;
@@ -882,7 +887,7 @@ static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 329 "parser.rl"
+#line 334 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -890,15 +895,15 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 894 "parser.c"
+#line 899 "parser.c"
{
cs = JSON_float_start;
}
-#line 336 "parser.rl"
+#line 341 "parser.rl"
json->memo = p;
-#line 902 "parser.c"
+#line 907 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -956,14 +961,14 @@ case 8:
goto st0;
goto tr9;
tr9:
-#line 323 "parser.rl"
+#line 328 "parser.rl"
{ p--; {p++; cs = 9; goto _out;} }
goto st9;
st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 967 "parser.c"
+#line 972 "parser.c"
goto st0;
st5:
if ( ++p == pe )
@@ -1024,7 +1029,7 @@ case 7:
_out: {}
}
-#line 338 "parser.rl"
+#line 343 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -1040,7 +1045,7 @@ case 7:
-#line 1044 "parser.c"
+#line 1049 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
@@ -1048,7 +1053,7 @@ static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 381 "parser.rl"
+#line 386 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -1062,14 +1067,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
-#line 1066 "parser.c"
+#line 1071 "parser.c"
{
cs = JSON_array_start;
}
-#line 394 "parser.rl"
+#line 399 "parser.rl"
-#line 1073 "parser.c"
+#line 1078 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1108,7 +1113,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 358 "parser.rl"
+#line 363 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -1128,7 +1133,7 @@ case 2:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 1132 "parser.c"
+#line 1137 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1228,14 +1233,14 @@ case 12:
goto st3;
goto st12;
tr4:
-#line 373 "parser.rl"
+#line 378 "parser.rl"
{ p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
goto _test_eof17;
case 17:
-#line 1239 "parser.c"
+#line 1244 "parser.c"
goto st0;
st13:
if ( ++p == pe )
@@ -1291,7 +1296,7 @@ case 16:
_out: {}
}
-#line 395 "parser.rl"
+#line 400 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
@@ -1372,7 +1377,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
}
-#line 1376 "parser.c"
+#line 1381 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
@@ -1380,7 +1385,7 @@ static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 494 "parser.rl"
+#line 499 "parser.rl"
static int
@@ -1402,15 +1407,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_str_buf_new(0);
-#line 1406 "parser.c"
+#line 1411 "parser.c"
{
cs = JSON_string_start;
}
-#line 515 "parser.rl"
+#line 520 "parser.rl"
json->memo = p;
-#line 1414 "parser.c"
+#line 1419 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1435,7 +1440,7 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 480 "parser.rl"
+#line 485 "parser.rl"
{
*result = json_string_unescape(*result, json->memo + 1, p);
if (NIL_P(*result)) {
@@ -1446,14 +1451,14 @@ case 2:
{p = (( p + 1))-1;}
}
}
-#line 491 "parser.rl"
+#line 496 "parser.rl"
{ p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
-#line 1457 "parser.c"
+#line 1462 "parser.c"
goto st0;
st3:
if ( ++p == pe )
@@ -1529,7 +1534,7 @@ case 7:
_out: {}
}
-#line 517 "parser.rl"
+#line 522 "parser.rl"
if (json->create_additions && RTEST(match_string = json->match_string)) {
VALUE klass;
@@ -1678,7 +1683,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
tmp = ID2SYM(i_create_additions);
if (option_given_p(opts, tmp)) {
- json->create_additions = RTEST(rb_hash_aref(opts, tmp));
+ VALUE create_additions = rb_hash_aref(opts, tmp);
+ if (rb_class_of(create_additions) == rb_cProc){
+ json->create_additions = create_additions;
+ }else{
+ json->create_additions = RTEST(create_additions);
+ }
} else {
json->create_additions = 0;
}
@@ -1729,7 +1739,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
-#line 1733 "parser.c"
+#line 1743 "parser.c"
static const int JSON_start = 1;
static const int JSON_first_final = 10;
static const int JSON_error = 0;
@@ -1737,7 +1747,7 @@ static const int JSON_error = 0;
static const int JSON_en_main = 1;
-#line 740 "parser.rl"
+#line 750 "parser.rl"
static VALUE cParser_parse_strict(VALUE self)
@@ -1748,16 +1758,16 @@ static VALUE cParser_parse_strict(VALUE self)
GET_PARSER;
-#line 1752 "parser.c"
+#line 1762 "parser.c"
{
cs = JSON_start;
}
-#line 750 "parser.rl"
+#line 760 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1761 "parser.c"
+#line 1771 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1813,7 +1823,7 @@ case 5:
goto st1;
goto st5;
tr3:
-#line 729 "parser.rl"
+#line 739 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1822,7 +1832,7 @@ case 5:
}
goto st10;
tr4:
-#line 722 "parser.rl"
+#line 732 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1834,7 +1844,7 @@ case 5:
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 1838 "parser.c"
+#line 1848 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1891,7 +1901,7 @@ case 9:
_out: {}
}
-#line 753 "parser.rl"
+#line 763 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -1903,7 +1913,7 @@ case 9:
-#line 1907 "parser.c"
+#line 1917 "parser.c"
static const int JSON_quirks_mode_start = 1;
static const int JSON_quirks_mode_first_final = 10;
static const int JSON_quirks_mode_error = 0;
@@ -1911,7 +1921,7 @@ static const int JSON_quirks_mode_error = 0;
static const int JSON_quirks_mode_en_main = 1;
-#line 778 "parser.rl"
+#line 788 "parser.rl"
static VALUE cParser_parse_quirks_mode(VALUE self)
@@ -1922,16 +1932,16 @@ static VALUE cParser_parse_quirks_mode(VALUE self)
GET_PARSER;
-#line 1926 "parser.c"
+#line 1936 "parser.c"
{
cs = JSON_quirks_mode_start;
}
-#line 788 "parser.rl"
+#line 798 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1935 "parser.c"
+#line 1945 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1965,7 +1975,7 @@ case 1:
cs = 0;
goto _out;
tr2:
-#line 770 "parser.rl"
+#line 780 "parser.rl"
{
char *np = JSON_parse_value(json, p, pe, &result);
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -1975,7 +1985,7 @@ cs = 0;
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 1979 "parser.c"
+#line 1989 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -2064,7 +2074,7 @@ case 9:
_out: {}
}
-#line 791 "parser.rl"
+#line 801 "parser.rl"
if (cs >= JSON_quirks_mode_first_final && p == pe) {
return result;
@@ -2181,6 +2191,7 @@ void Init_parser()
i_aset = rb_intern("[]=");
i_aref = rb_intern("[]");
i_leftshift = rb_intern("<<");
+ i_call = rb_intern("call");
#ifdef HAVE_RUBY_ENCODING_H
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
2  ext/json/ext/parser/parser.h
View
@@ -41,7 +41,7 @@ typedef struct JSON_ParserStruct {
int quirks_mode;
VALUE object_class;
VALUE array_class;
- int create_additions;
+ VALUE create_additions;
VALUE match_string;
FBuffer *fbuffer;
} JSON_Parser;
17 ext/json/ext/parser/parser.rl
View
@@ -79,7 +79,7 @@ static VALUE CNaN, CInfinity, CMinusInfinity;
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, i_quirks_mode,
i_object_class, i_array_class, i_key_p, i_deep_const_get, i_match,
- i_match_string, i_aset, i_aref, i_leftshift;
+ i_match_string, i_aset, i_aref, i_leftshift, i_call;
%%{
machine JSON_common;
@@ -174,7 +174,12 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
klassname = rb_funcall(*result, i_aref, 1, json->create_id);
}
if (!NIL_P(klassname)) {
- VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
+ VALUE klass = NULL;
+ if(rb_class_of(json->create_additions) == rb_cProc)
+ klass = rb_funcall(json->create_additions, i_call, 1, klassname);
+ else
+ klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
+
if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
*result = rb_funcall(klass, i_json_create, 1, *result);
}
@@ -662,7 +667,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
tmp = ID2SYM(i_create_additions);
if (option_given_p(opts, tmp)) {
- json->create_additions = RTEST(rb_hash_aref(opts, tmp));
+ VALUE create_additions = rb_hash_aref(opts, tmp);
+ if (rb_class_of(create_additions) == rb_cProc){
+ json->create_additions = create_additions;
+ }else{
+ json->create_additions = RTEST(create_additions);
+ }
} else {
json->create_additions = 0;
}
@@ -904,6 +914,7 @@ void Init_parser()
i_aset = rb_intern("[]=");
i_aref = rb_intern("[]");
i_leftshift = rb_intern("<<");
+ i_call = rb_intern("call");
#ifdef HAVE_RUBY_ENCODING_H
CEncoding_UTF_8 = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-8"));
CEncoding_UTF_16BE = rb_funcall(rb_path2class("Encoding"), rb_intern("find"), 1, rb_str_new2("utf-16be"));
8 java/src/json/ext/OptionsReader.java
View
@@ -11,6 +11,7 @@
import org.jruby.RubyHash;
import org.jruby.RubyNumeric;
import org.jruby.RubyString;
+import org.jruby.RubyObject;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.ByteList;
@@ -111,4 +112,11 @@ public RubyHash getHash(String key) {
if (value == null || value.isNil()) return new RubyHash(runtime);
return (RubyHash) value;
}
+
+ RubyObject getObject(String key, RubyObject defaultValue) {
+ IRubyObject value = get(key);
+
+ if (value == null || value.isNil()) return defaultValue;
+ return (RubyObject)value;
+ }
}
186 java/src/json/ext/Parser.java
View
@@ -19,6 +19,7 @@
import org.jruby.RubyNumeric;
import org.jruby.RubyObject;
import org.jruby.RubyString;
+import org.jruby.RubyProc;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.JumpException;
import org.jruby.exceptions.RaiseException;
@@ -49,7 +50,7 @@
private final RuntimeInfo info;
private RubyString vSource;
private RubyString createId;
- private boolean createAdditions;
+ private RubyObject createAdditions;
private int maxNesting;
private boolean allowNaN;
private boolean symbolizeNames;
@@ -166,7 +167,7 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args) {
this.symbolizeNames = opts.getBool("symbolize_names", false);
this.quirksMode = opts.getBool("quirks_mode", false);
this.createId = opts.getString("create_id", getCreateId(context));
- this.createAdditions = opts.getBool("create_additions", false);
+ this.createAdditions = opts.getObject("create_additions", runtime.getFalse());
this.objectClass = opts.getClass("object_class", runtime.getHash());
this.arrayClass = opts.getClass("array_class", runtime.getArray());
this.match_string = opts.getHash("match_string");
@@ -337,11 +338,11 @@ private Ruby getRuntime() {
}
-// line 363 "Parser.rl"
+// line 364 "Parser.rl"
-// line 345 "Parser.java"
+// line 346 "Parser.java"
private static byte[] init__JSON_value_actions_0()
{
return new byte [] {
@@ -455,7 +456,7 @@ private Ruby getRuntime() {
static final int JSON_value_en_main = 1;
-// line 469 "Parser.rl"
+// line 470 "Parser.rl"
void parseValue(ParserResult res, int p, int pe) {
@@ -463,14 +464,14 @@ void parseValue(ParserResult res, int p, int pe) {
IRubyObject result = null;
-// line 467 "Parser.java"
+// line 468 "Parser.java"
{
cs = JSON_value_start;
}
-// line 476 "Parser.rl"
+// line 477 "Parser.rl"
-// line 474 "Parser.java"
+// line 475 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -496,13 +497,13 @@ void parseValue(ParserResult res, int p, int pe) {
while ( _nacts-- > 0 ) {
switch ( _JSON_value_actions[_acts++] ) {
case 9:
-// line 454 "Parser.rl"
+// line 455 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 506 "Parser.java"
+// line 507 "Parser.java"
}
}
@@ -565,25 +566,25 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
switch ( _JSON_value_actions[_acts++] )
{
case 0:
-// line 371 "Parser.rl"
+// line 372 "Parser.rl"
{
result = getRuntime().getNil();
}
break;
case 1:
-// line 374 "Parser.rl"
+// line 375 "Parser.rl"
{
result = getRuntime().getFalse();
}
break;
case 2:
-// line 377 "Parser.rl"
+// line 378 "Parser.rl"
{
result = getRuntime().getTrue();
}
break;
case 3:
-// line 380 "Parser.rl"
+// line 381 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_NAN);
@@ -593,7 +594,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 4:
-// line 387 "Parser.rl"
+// line 388 "Parser.rl"
{
if (parser.allowNaN) {
result = getConstant(CONST_INFINITY);
@@ -603,7 +604,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 5:
-// line 394 "Parser.rl"
+// line 395 "Parser.rl"
{
if (pe > p + 9 - (parser.quirksMode ? 1 : 0) &&
absSubSequence(p, p + 9).equals(JSON_MINUS_INFINITY)) {
@@ -632,7 +633,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 6:
-// line 420 "Parser.rl"
+// line 421 "Parser.rl"
{
parseString(res, p, pe);
if (res.result == null) {
@@ -645,7 +646,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 7:
-// line 430 "Parser.rl"
+// line 431 "Parser.rl"
{
currentNesting++;
parseArray(res, p, pe);
@@ -660,7 +661,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
break;
case 8:
-// line 442 "Parser.rl"
+// line 443 "Parser.rl"
{
currentNesting++;
parseObject(res, p, pe);
@@ -674,7 +675,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
}
break;
-// line 678 "Parser.java"
+// line 679 "Parser.java"
}
}
}
@@ -694,7 +695,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
break; }
}
-// line 477 "Parser.rl"
+// line 478 "Parser.rl"
if (cs >= JSON_value_first_final && result != null) {
res.update(result, p);
@@ -704,7 +705,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
}
-// line 708 "Parser.java"
+// line 709 "Parser.java"
private static byte[] init__JSON_integer_actions_0()
{
return new byte [] {
@@ -803,7 +804,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] )
static final int JSON_integer_en_main = 1;
-// line 496 "Parser.rl"
+// line 497 "Parser.rl"
void parseInteger(ParserResult res, int p, int pe) {
@@ -821,15 +822,15 @@ int parseIntegerInternal(int p, int pe) {
int cs = EVIL;
-// line 825 "Parser.java"
+// line 826 "Parser.java"
{
cs = JSON_integer_start;
}
-// line 513 "Parser.rl"
+// line 514 "Parser.rl"
int memo = p;
-// line 833 "Parser.java"
+// line 834 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -910,13 +911,13 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] )
switch ( _JSON_integer_actions[_acts++] )
{
case 0:
-// line 490 "Parser.rl"
+// line 491 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 920 "Parser.java"
+// line 921 "Parser.java"
}
}
}
@@ -936,7 +937,7 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] )
break; }
}
-// line 515 "Parser.rl"
+// line 516 "Parser.rl"
if (cs < JSON_integer_first_final) {
return -1;
@@ -958,7 +959,7 @@ RubyInteger bytesToInum(Ruby runtime, ByteList num) {
}
-// line 962 "Parser.java"
+// line 963 "Parser.java"
private static byte[] init__JSON_float_actions_0()
{
return new byte [] {
@@ -1060,7 +1061,7 @@ RubyInteger bytesToInum(Ruby runtime, ByteList num) {
static final int JSON_float_en_main = 1;
-// line 550 "Parser.rl"
+// line 551 "Parser.rl"
void parseFloat(ParserResult res, int p, int pe) {
@@ -1078,15 +1079,15 @@ int parseFloatInternal(int p, int pe) {
int cs = EVIL;
-// line 1082 "Parser.java"
+// line 1083 "Parser.java"
{
cs = JSON_float_start;
}
-// line 567 "Parser.rl"
+// line 568 "Parser.rl"
int memo = p;
-// line 1090 "Parser.java"
+// line 1091 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1167,13 +1168,13 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] )
switch ( _JSON_float_actions[_acts++] )
{
case 0:
-// line 541 "Parser.rl"
+// line 542 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1177 "Parser.java"
+// line 1178 "Parser.java"
}
}
}
@@ -1193,7 +1194,7 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] )
break; }
}
-// line 569 "Parser.rl"
+// line 570 "Parser.rl"
if (cs < JSON_float_first_final) {
return -1;
@@ -1209,7 +1210,7 @@ RubyFloat createFloat(int p, int new_p) {
}
-// line 1213 "Parser.java"
+// line 1214 "Parser.java"
private static byte[] init__JSON_string_actions_0()
{
return new byte [] {
@@ -1311,7 +1312,7 @@ RubyFloat createFloat(int p, int new_p) {
static final int JSON_string_en_main = 1;
-// line 614 "Parser.rl"
+// line 615 "Parser.rl"
void parseString(ParserResult res, int p, int pe) {
@@ -1319,15 +1320,15 @@ void parseString(ParserResult res, int p, int pe) {
IRubyObject result = null;
-// line 1323 "Parser.java"
+// line 1324 "Parser.java"
{
cs = JSON_string_start;
}
-// line 621 "Parser.rl"
+// line 622 "Parser.rl"
int memo = p;
-// line 1331 "Parser.java"
+// line 1332 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1408,7 +1409,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] )
switch ( _JSON_string_actions[_acts++] )
{
case 0:
-// line 589 "Parser.rl"
+// line 590 "Parser.rl"
{
int offset = byteList.begin();
ByteList decoded = decoder.decode(byteList, memo + 1 - offset,
@@ -1423,13 +1424,13 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] )
}
break;
case 1:
-// line 602 "Parser.rl"
+// line 603 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1433 "Parser.java"
+// line 1434 "Parser.java"
}
}
}
@@ -1449,9 +1450,9 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] )
break; }
}
-// line 623 "Parser.rl"
+// line 624 "Parser.rl"
- if (parser.createAdditions) {
+ if (!parser.createAdditions.isFalse()) {
RubyHash match_string = parser.match_string;
if (match_string != null) {
final IRubyObject[] memoArray = { result, null };
@@ -1488,7 +1489,7 @@ public void visit(IRubyObject pattern, IRubyObject klass) {
}
-// line 1492 "Parser.java"
+// line 1493 "Parser.java"
private static byte[] init__JSON_array_actions_0()
{
return new byte [] {
@@ -1601,7 +1602,7 @@ public void visit(IRubyObject pattern, IRubyObject klass) {
static final int JSON_array_en_main = 1;
-// line 697 "Parser.rl"
+// line 698 "Parser.rl"
void parseArray(ParserResult res, int p, int pe) {
@@ -1621,14 +1622,14 @@ void parseArray(ParserResult res, int p, int pe) {
}
-// line 1625 "Parser.java"
+// line 1626 "Parser.java"
{
cs = JSON_array_start;
}
-// line 716 "Parser.rl"
+// line 717 "Parser.rl"
-// line 1632 "Parser.java"
+// line 1633 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1709,7 +1710,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] )
switch ( _JSON_array_actions[_acts++] )
{
case 0:
-// line 666 "Parser.rl"
+// line 667 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -1726,13 +1727,13 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] )
}
break;
case 1:
-// line 681 "Parser.rl"
+// line 682 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 1736 "Parser.java"
+// line 1737 "Parser.java"
}
}
}
@@ -1752,7 +1753,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] )
break; }
}
-// line 717 "Parser.rl"
+// line 718 "Parser.rl"
if (cs >= JSON_array_first_final) {
res.update(result, p + 1);
@@ -1762,7 +1763,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] )
}
-// line 1766 "Parser.java"
+// line 1767 "Parser.java"
private static byte[] init__JSON_object_actions_0()
{
return new byte [] {
@@ -1885,7 +1886,7 @@ else if ( data[p] > _JSON_array_trans_keys[_mid+1] )
static final int JSON_object_en_main = 1;
-// line 776 "Parser.rl"
+// line 777 "Parser.rl"
void parseObject(ParserResult res, int p, int pe) {
@@ -1910,14 +1911,14 @@ void parseObject(ParserResult res, int p, int pe) {
}
-// line 1914 "Parser.java"
+// line 1915 "Parser.java"
{
cs = JSON_object_start;
}
-// line 800 "Parser.rl"
+// line 801 "Parser.rl"
-// line 1921 "Parser.java"
+// line 1922 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -1998,7 +1999,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
switch ( _JSON_object_actions[_acts++] )
{
case 0:
-// line 731 "Parser.rl"
+// line 732 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -2015,7 +2016,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
}
break;
case 1:
-// line 746 "Parser.rl"
+// line 747 "Parser.rl"
{
parseString(res, p, pe);
if (res.result == null) {
@@ -2035,13 +2036,13 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
}
break;
case 2:
-// line 764 "Parser.rl"
+// line 765 "Parser.rl"
{
p--;
{ p += 1; _goto_targ = 5; if (true) continue _goto;}
}
break;
-// line 2045 "Parser.java"
+// line 2046 "Parser.java"
}
}
}
@@ -2061,7 +2062,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
break; }
}
-// line 801 "Parser.rl"
+// line 802 "Parser.rl"
if (cs < JSON_object_first_final) {
res.update(null, p + 1);
@@ -2071,7 +2072,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
IRubyObject returnedResult = result;
// attempt to de-serialize object
- if (parser.createAdditions) {
+ if (!parser.createAdditions.isFalse()) {
IRubyObject vKlassName;
if (objectDefault) {
vKlassName = ((RubyHash)result).op_aref(context, parser.createId);
@@ -2080,10 +2081,19 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
}
if (!vKlassName.isNil()) {
- // might throw ArgumentError, we let it propagate
- IRubyObject klass = parser.info.jsonModule.get().
- callMethod(context, "deep_const_get", vKlassName);
- if (klass.respondsTo("json_creatable?") &&
+ IRubyObject klass = null;
+ if(parser.createAdditions instanceof RubyProc){
+ klass =
+ ((RubyProc)parser.createAdditions).
+ call(context, new IRubyObject[]{vKlassName});
+ }else{
+ // might throw ArgumentError, we let it propagate
+ klass = parser.info.jsonModule.get().
+ callMethod(context, "deep_const_get", vKlassName);
+ }
+
+ if (klass != null &&
+ klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
returnedResult = klass.callMethod(context, "json_create", result);
@@ -2094,7 +2104,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
}
-// line 2098 "Parser.java"
+// line 2108 "Parser.java"
private static byte[] init__JSON_actions_0()
{
return new byte [] {
@@ -2198,7 +2208,7 @@ else if ( data[p] > _JSON_object_trans_keys[_mid+1] )
static final int JSON_en_main = 1;
-// line 866 "Parser.rl"
+// line 876 "Parser.rl"
public IRubyObject parseStrict() {
@@ -2208,16 +2218,16 @@ public IRubyObject parseStrict() {
ParserResult res = new ParserResult();
-// line 2212 "Parser.java"
+// line 2222 "Parser.java"
{
cs = JSON_start;
}
-// line 875 "Parser.rl"
+// line 885 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2221 "Parser.java"
+// line 2231 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2298,7 +2308,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
switch ( _JSON_actions[_acts++] )
{
case 0:
-// line 838 "Parser.rl"
+// line 848 "Parser.rl"
{
currentNesting = 1;
parseObject(res, p, pe);
@@ -2312,7 +2322,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
}
break;
case 1:
-// line 850 "Parser.rl"
+// line 860 "Parser.rl"
{
currentNesting = 1;
parseArray(res, p, pe);
@@ -2325,7 +2335,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
}
}
break;
-// line 2329 "Parser.java"
+// line 2339 "Parser.java"
}
}
}
@@ -2345,7 +2355,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
break; }
}
-// line 878 "Parser.rl"
+// line 888 "Parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -2355,7 +2365,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
}
-// line 2359 "Parser.java"
+// line 2369 "Parser.java"
private static byte[] init__JSON_quirks_mode_actions_0()
{
return new byte [] {
@@ -2458,7 +2468,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] )
static final int JSON_quirks_mode_en_main = 1;
-// line 906 "Parser.rl"
+// line 916 "Parser.rl"
public IRubyObject parseQuirksMode() {
@@ -2468,16 +2478,16 @@ public IRubyObject parseQuirksMode() {
ParserResult res = new ParserResult();
-// line 2472 "Parser.java"
+// line 2482 "Parser.java"
{
cs = JSON_quirks_mode_start;
}
-// line 915 "Parser.rl"
+// line 925 "Parser.rl"
p = byteList.begin();
pe = p + byteList.length();
-// line 2481 "Parser.java"
+// line 2491 "Parser.java"
{
int _klen;
int _trans = 0;
@@ -2558,7 +2568,7 @@ else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid+1] )
switch ( _JSON_quirks_mode_actions[_acts++] )
{
case 0:
-// line 892 "Parser.rl"
+// line 902 "Parser.rl"
{
parseValue(res, p, pe);
if (res.result == null) {
@@ -2570,7 +2580,7 @@ else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid+1] )
}
}
break;
-// line 2574 "Parser.java"
+// line 2584 "Parser.java"
}
}
}
@@ -2590,7 +2600,7 @@ else if ( data[p] > _JSON_quirks_mode_trans_keys[_mid+1] )
break; }
}
-// line 918 "Parser.rl"
+// line 928 "Parser.rl"
if (cs >= JSON_quirks_mode_first_final && p == pe) {
return result;
25 java/src/json/ext/Parser.rl
View
@@ -17,6 +17,7 @@ import org.jruby.RubyModule;
import org.jruby.RubyNumeric;
import org.jruby.RubyObject;
import org.jruby.RubyString;
+import org.jruby.RubyProc;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.JumpException;
import org.jruby.exceptions.RaiseException;
@@ -47,7 +48,7 @@ public class Parser extends RubyObject {
private final RuntimeInfo info;
private RubyString vSource;
private RubyString createId;
- private boolean createAdditions;
+ private RubyObject createAdditions;
private int maxNesting;
private boolean allowNaN;
private boolean symbolizeNames;
@@ -164,7 +165,7 @@ public class Parser extends RubyObject {
this.symbolizeNames = opts.getBool("symbolize_names", false);
this.quirksMode = opts.getBool("quirks_mode", false);
this.createId = opts.getString("create_id", getCreateId(context));
- this.createAdditions = opts.getBool("create_additions", false);
+ this.createAdditions = opts.getObject("create_additions", runtime.getFalse());
this.objectClass = opts.getClass("object_class", runtime.getHash());
this.arrayClass = opts.getClass("array_class", runtime.getArray());
this.match_string = opts.getHash("match_string");
@@ -621,7 +622,7 @@ public class Parser extends RubyObject {
int memo = p;
%% write exec;
- if (parser.createAdditions) {
+ if (!parser.createAdditions.equals(context.getRuntime().getFalse())) {
RubyHash match_string = parser.match_string;
if (match_string != null) {
final IRubyObject[] memoArray = { result, null };
@@ -807,7 +808,7 @@ public class Parser extends RubyObject {
IRubyObject returnedResult = result;
// attempt to de-serialize object
- if (parser.createAdditions) {
+ if (!parser.createAdditions.equals(context.getRuntime().getFalse())) {
IRubyObject vKlassName;
if (objectDefault) {
vKlassName = ((RubyHash)result).op_aref(context, parser.createId);
@@ -816,10 +817,18 @@ public class Parser extends RubyObject {
}
if (!vKlassName.isNil()) {
- // might throw ArgumentError, we let it propagate
- IRubyObject klass = parser.info.jsonModule.get().
- callMethod(context, "deep_const_get", vKlassName);
- if (klass.respondsTo("json_creatable?") &&
+ IRubyObject klass = null;
+ if(parser.createAdditions instanceof RubyProc){
+ klass = ((RubyProc)parser.createAdditions).
+ call(context, new IRubyObject[]{vKlassName});
+ }else{
+ // might throw ArgumentError, we let it propagate
+ klass = parser.info.jsonModule.get().
+ callMethod(context, "deep_const_get", vKlassName);
+ }
+
+ if (klass != null &&
+ klass.respondsTo("json_creatable?") &&
klass.callMethod(context, "json_creatable?").isTrue()) {
returnedResult = klass.callMethod(context, "json_create", result);
13 lib/json/pure/parser.rb
View
@@ -86,7 +86,11 @@ def initialize(source, opts = {})
@allow_nan = !!opts[:allow_nan]
@symbolize_names = !!opts[:symbolize_names]
if opts.key?(:create_additions)
- @create_additions = !!opts[:create_additions]
+ if opts[:create_additions].is_a?(Proc)
+ @create_additions = opts[:create_additions]
+ else
+ @create_additions = !!opts[:create_additions]
+ end
else
@create_additions = false
end
@@ -341,7 +345,12 @@ def parse_object
raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
end
if @create_additions and klassname = result[@create_id]
- klass = JSON.deep_const_get klassname
+ klass = nil
+ if @create_additions.is_a?(Proc)
+ klass = @create_additions.call klassname
+ else
+ klass = JSON.deep_const_get klassname
+ end
break unless klass and klass.json_creatable?
result = klass.json_create(result)
end
9 tests/test_json_addition.rb
View
@@ -101,6 +101,15 @@ def test_extended_json_disabled
)
end
+ def test_extended_json_custom_matcher
+ a = A.new(666)
+ assert A.json_creatable?
+ json = generate(a)
+ a_again = JSON.parse(json, :create_additions => proc { |e| A2 })
+ assert_kind_of A2, a_again
+ assert_equal a, a_again
+ end
+
def test_extended_json_fail1
b = B.new
assert !B.json_creatable?
Something went wrong with that request. Please try again.