From 01c47a055574d86619f5687b9928a14147cba4ee Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 27 Mar 2025 10:16:10 +0100 Subject: [PATCH 1/4] Cleanup JSON.pretty_generate --- lib/json/common.rb | 45 ++++++++++++++++---------------- test/json/json_generator_test.rb | 21 +-------------- 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/lib/json/common.rb b/lib/json/common.rb index c9f6d7505..1d939b7d1 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -74,15 +74,6 @@ def generator=(generator) # :nodoc: $VERBOSE = old end - def create_pretty_state - State.new( - :indent => ' ', - :space => ' ', - :object_nl => "\n", - :array_nl => "\n" - ) - end - # Returns the JSON generator module that is used by JSON. attr_reader :generator @@ -366,6 +357,14 @@ def fast_generate(obj, opts = nil) generate(obj, opts) end + PRETTY_GENERATE_OPTIONS = { + indent: ' ', + space: ' ', + object_nl: "\n", + array_nl: "\n", + }.freeze + private_constant :PRETTY_GENERATE_OPTIONS + # :call-seq: # JSON.pretty_generate(obj, opts = nil) -> new_string # @@ -397,22 +396,24 @@ def fast_generate(obj, opts = nil) # } # def pretty_generate(obj, opts = nil) - if State === opts - state, opts = opts, nil - else - state = JSON.create_pretty_state - end + return state.generate(obj) if State === opts + + options = PRETTY_GENERATE_OPTIONS + if opts - if opts.respond_to? :to_hash - opts = opts.to_hash - elsif opts.respond_to? :to_h - opts = opts.to_h - else - raise TypeError, "can't convert #{opts.class} into Hash" + unless opts.is_a?(Hash) + if opts.respond_to? :to_hash + opts = opts.to_hash + elsif opts.respond_to? :to_h + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end end - state.configure(opts) + options = options.merge(opts) end - state.generate(obj) + + State.generate(obj, options, nil) end # Sets or returns default options for the JSON.unsafe_load method. diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index 64636c12c..05006ebd0 100755 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -199,26 +199,7 @@ def test_falsy_state ) end - def test_pretty_state - state = JSON.create_pretty_state - assert_equal({ - :allow_nan => false, - :array_nl => "\n", - :as_json => false, - :ascii_only => false, - :buffer_initial_length => 1024, - :depth => 0, - :script_safe => false, - :strict => false, - :indent => " ", - :max_nesting => 100, - :object_nl => "\n", - :space => " ", - :space_before => "", - }.sort_by { |n,| n.to_s }, state.to_h.sort_by { |n,| n.to_s }) - end - - def test_safe_state + def test_state_defaults state = JSON::State.new assert_equal({ :allow_nan => false, From 3de8702354395121357b94aff3d68935a9ac709f Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 27 Mar 2025 10:16:14 +0100 Subject: [PATCH 2/4] Remove outdated JSON.iconv --- CHANGES.md | 1 + lib/json/common.rb | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9e00cd543..b1d705426 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ * Deprecate `JSON.load_default_options`. * Deprecate `JSON.unsafe_load_default_options`. * Deprecate `JSON.dump_default_options`. +* Remove outdated `JSON.iconv`. * Remove deprecated `JSON.restore` method. * Remove deprecated `JSON.unparse` method. * Remove deprecated `JSON.fast_unparse` method. diff --git a/lib/json/common.rb b/lib/json/common.rb index 1d939b7d1..24f124baa 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -837,11 +837,6 @@ def dump(obj, anIO = nil, limit = nil, kwargs = nil) end end - # Encodes string using String.encode. - def self.iconv(to, from, string) - string.encode(to, from) - end - # JSON::Coder holds a parser and generator configuration. # # module MyApp From 760d9222657a7d6625f11aa1c6eba4058ae29722 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 27 Mar 2025 10:36:31 +0100 Subject: [PATCH 3/4] Get rid of JSON::NOT_SET --- lib/json/common.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/json/common.rb b/lib/json/common.rb index 24f124baa..30fdbe1db 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -5,9 +5,6 @@ module JSON autoload :GenericObject, 'json/generic_object' - NOT_SET = Object.new.freeze - private_constant :NOT_SET - class << self # :call-seq: # JSON[object] -> new_array or new_string From 1ca7efed1f6e13d48934cd12c403d2ed08ac9fc1 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 27 Mar 2025 10:34:17 +0100 Subject: [PATCH 4/4] Remove `Class#json_creatable?` monkey patch. --- CHANGES.md | 1 + ext/json/ext/parser/parser.c | 13 ++- java/src/json/ext/ParserConfig.java | 160 +++++++++++++++------------- java/src/json/ext/ParserConfig.rl | 14 ++- lib/json/common.rb | 11 -- test/json/json_addition_test.rb | 14 +-- 6 files changed, 106 insertions(+), 107 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b1d705426..743b9e5a2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ * Deprecate `JSON.unsafe_load_default_options`. * Deprecate `JSON.dump_default_options`. * Remove outdated `JSON.iconv`. +* Remove `Class#json_creatable?` monkey patch. * Remove deprecated `JSON.restore` method. * Remove deprecated `JSON.unparse` method. * Remove deprecated `JSON.fast_unparse` method. diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index d990612a2..d2d0d38d8 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -790,6 +790,15 @@ static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig return array; } +static bool json_obj_creatable_p(VALUE klass) +{ + if (rb_respond_to(klass, i_json_creatable_p)) { + return RTEST(rb_funcall(klass, i_json_creatable_p, 0)); + } else { + return rb_respond_to(klass, i_json_create); + } +} + static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, long count) { VALUE object; @@ -818,7 +827,7 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi } if (!NIL_P(klassname)) { VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname); - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) { + if (json_obj_creatable_p(klass)) { if (config->deprecated_create_additions) { json_deprecated(deprecated_create_additions_warning); } @@ -837,7 +846,7 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi static int match_i(VALUE regexp, VALUE klass, VALUE memo) { if (regexp == Qundef) return ST_STOP; - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) && + if (json_obj_creatable_p(klass) && RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) { rb_ary_push(memo, klass); return ST_STOP; diff --git a/java/src/json/ext/ParserConfig.java b/java/src/json/ext/ParserConfig.java index 6596f97f0..83251fc8d 100644 --- a/java/src/json/ext/ParserConfig.java +++ b/java/src/json/ext/ParserConfig.java @@ -266,6 +266,14 @@ private IRubyObject createCustomDecimal(final ThreadContext context, final ByteL return decimalClass.newInstance(context, context.runtime.newString(num), Block.NULL_BLOCK); } + private static boolean isObjCreateable(final ThreadContext context, IRubyObject klass) { + if (klass.respondsTo("json_creatable?")) { + return klass.callMethod(context, "json_creatable?").isTrue(); + } else { + return klass.respondsTo("json_create"); + } + } + /** * A string parsing session. * @@ -303,11 +311,11 @@ private RaiseException unexpectedToken(ThreadContext context, int absStart, int } -// line 329 "ParserConfig.rl" +// line 337 "ParserConfig.rl" -// line 311 "ParserConfig.java" +// line 319 "ParserConfig.java" private static byte[] init__JSON_value_actions_0() { return new byte [] { @@ -421,7 +429,7 @@ private static byte[] init__JSON_value_from_state_actions_0() static final int JSON_value_en_main = 1; -// line 435 "ParserConfig.rl" +// line 443 "ParserConfig.rl" void parseValue(ThreadContext context, ParserResult res, int p, int pe) { @@ -429,14 +437,14 @@ void parseValue(ThreadContext context, ParserResult res, int p, int pe) { IRubyObject result = null; -// line 433 "ParserConfig.java" +// line 441 "ParserConfig.java" { cs = JSON_value_start; } -// line 442 "ParserConfig.rl" +// line 450 "ParserConfig.rl" -// line 440 "ParserConfig.java" +// line 448 "ParserConfig.java" { int _klen; int _trans = 0; @@ -462,13 +470,13 @@ void parseValue(ThreadContext context, ParserResult res, int p, int pe) { while ( _nacts-- > 0 ) { switch ( _JSON_value_actions[_acts++] ) { case 9: -// line 420 "ParserConfig.rl" +// line 428 "ParserConfig.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 472 "ParserConfig.java" +// line 480 "ParserConfig.java" } } @@ -531,25 +539,25 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) switch ( _JSON_value_actions[_acts++] ) { case 0: -// line 337 "ParserConfig.rl" +// line 345 "ParserConfig.rl" { result = context.nil; } break; case 1: -// line 340 "ParserConfig.rl" +// line 348 "ParserConfig.rl" { result = context.fals; } break; case 2: -// line 343 "ParserConfig.rl" +// line 351 "ParserConfig.rl" { result = context.tru; } break; case 3: -// line 346 "ParserConfig.rl" +// line 354 "ParserConfig.rl" { if (config.allowNaN) { result = getConstant(CONST_NAN); @@ -559,7 +567,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 4: -// line 353 "ParserConfig.rl" +// line 361 "ParserConfig.rl" { if (config.allowNaN) { result = getConstant(CONST_INFINITY); @@ -569,7 +577,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 5: -// line 360 "ParserConfig.rl" +// line 368 "ParserConfig.rl" { if (pe > p + 8 && absSubSequence(p, p + 9).equals(JSON_MINUS_INFINITY)) { @@ -598,7 +606,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 6: -// line 386 "ParserConfig.rl" +// line 394 "ParserConfig.rl" { parseString(context, res, p, pe); if (res.result == null) { @@ -611,7 +619,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 7: -// line 396 "ParserConfig.rl" +// line 404 "ParserConfig.rl" { currentNesting++; parseArray(context, res, p, pe); @@ -626,7 +634,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } break; case 8: -// line 408 "ParserConfig.rl" +// line 416 "ParserConfig.rl" { currentNesting++; parseObject(context, res, p, pe); @@ -640,7 +648,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } } break; -// line 644 "ParserConfig.java" +// line 652 "ParserConfig.java" } } } @@ -660,7 +668,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) break; } } -// line 443 "ParserConfig.rl" +// line 451 "ParserConfig.rl" if (cs >= JSON_value_first_final && result != null) { if (config.freeze) { @@ -673,7 +681,7 @@ else if ( data[p] > _JSON_value_trans_keys[_mid+1] ) } -// line 677 "ParserConfig.java" +// line 685 "ParserConfig.java" private static byte[] init__JSON_integer_actions_0() { return new byte [] { @@ -772,7 +780,7 @@ private static byte[] init__JSON_integer_trans_actions_0() static final int JSON_integer_en_main = 1; -// line 465 "ParserConfig.rl" +// line 473 "ParserConfig.rl" void parseInteger(ThreadContext context, ParserResult res, int p, int pe) { @@ -789,15 +797,15 @@ int parseIntegerInternal(int p, int pe) { int cs; -// line 793 "ParserConfig.java" +// line 801 "ParserConfig.java" { cs = JSON_integer_start; } -// line 481 "ParserConfig.rl" +// line 489 "ParserConfig.rl" int memo = p; -// line 801 "ParserConfig.java" +// line 809 "ParserConfig.java" { int _klen; int _trans = 0; @@ -878,13 +886,13 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] ) switch ( _JSON_integer_actions[_acts++] ) { case 0: -// line 459 "ParserConfig.rl" +// line 467 "ParserConfig.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 888 "ParserConfig.java" +// line 896 "ParserConfig.java" } } } @@ -904,7 +912,7 @@ else if ( data[p] > _JSON_integer_trans_keys[_mid+1] ) break; } } -// line 483 "ParserConfig.rl" +// line 491 "ParserConfig.rl" if (cs < JSON_integer_first_final) { return -1; @@ -924,7 +932,7 @@ RubyInteger bytesToInum(Ruby runtime, ByteList num) { } -// line 928 "ParserConfig.java" +// line 936 "ParserConfig.java" private static byte[] init__JSON_float_actions_0() { return new byte [] { @@ -1026,7 +1034,7 @@ private static byte[] init__JSON_float_trans_actions_0() static final int JSON_float_en_main = 1; -// line 516 "ParserConfig.rl" +// line 524 "ParserConfig.rl" void parseFloat(ThreadContext context, ParserResult res, int p, int pe) { @@ -1045,15 +1053,15 @@ int parseFloatInternal(int p, int pe) { int cs; -// line 1049 "ParserConfig.java" +// line 1057 "ParserConfig.java" { cs = JSON_float_start; } -// line 534 "ParserConfig.rl" +// line 542 "ParserConfig.rl" int memo = p; -// line 1057 "ParserConfig.java" +// line 1065 "ParserConfig.java" { int _klen; int _trans = 0; @@ -1134,13 +1142,13 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] ) switch ( _JSON_float_actions[_acts++] ) { case 0: -// line 507 "ParserConfig.rl" +// line 515 "ParserConfig.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1144 "ParserConfig.java" +// line 1152 "ParserConfig.java" } } } @@ -1160,7 +1168,7 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] ) break; } } -// line 536 "ParserConfig.rl" +// line 544 "ParserConfig.rl" if (cs < JSON_float_first_final) { return -1; @@ -1170,7 +1178,7 @@ else if ( data[p] > _JSON_float_trans_keys[_mid+1] ) } -// line 1174 "ParserConfig.java" +// line 1182 "ParserConfig.java" private static byte[] init__JSON_string_actions_0() { return new byte [] { @@ -1272,7 +1280,7 @@ private static byte[] init__JSON_string_trans_actions_0() static final int JSON_string_en_main = 1; -// line 575 "ParserConfig.rl" +// line 583 "ParserConfig.rl" void parseString(ThreadContext context, ParserResult res, int p, int pe) { @@ -1280,15 +1288,15 @@ void parseString(ThreadContext context, ParserResult res, int p, int pe) { IRubyObject result = null; -// line 1284 "ParserConfig.java" +// line 1292 "ParserConfig.java" { cs = JSON_string_start; } -// line 582 "ParserConfig.rl" +// line 590 "ParserConfig.rl" int memo = p; -// line 1292 "ParserConfig.java" +// line 1300 "ParserConfig.java" { int _klen; int _trans = 0; @@ -1369,7 +1377,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) switch ( _JSON_string_actions[_acts++] ) { case 0: -// line 550 "ParserConfig.rl" +// line 558 "ParserConfig.rl" { int offset = byteList.begin(); ByteList decoded = decoder.decode(context, byteList, memo + 1 - offset, @@ -1384,13 +1392,13 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) } break; case 1: -// line 563 "ParserConfig.rl" +// line 571 "ParserConfig.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1394 "ParserConfig.java" +// line 1402 "ParserConfig.java" } } } @@ -1410,7 +1418,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) break; } } -// line 584 "ParserConfig.rl" +// line 592 "ParserConfig.rl" if (config.createAdditions) { RubyHash matchString = config.match_string; @@ -1421,8 +1429,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) } catch (JumpException e) { } if (memoArray[1] != null) { RubyClass klass = (RubyClass) memoArray[1]; - if (klass.respondsTo("json_creatable?") && - klass.callMethod(context, "json_creatable?").isTrue()) { + if (isObjCreateable(context, klass)) { if (config.deprecatedCreateAdditions) { context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`"); } @@ -1451,7 +1458,7 @@ else if ( data[p] > _JSON_string_trans_keys[_mid+1] ) } -// line 1455 "ParserConfig.java" +// line 1462 "ParserConfig.java" private static byte[] init__JSON_array_actions_0() { return new byte [] { @@ -1618,7 +1625,7 @@ private static byte[] init__JSON_array_trans_actions_0() static final int JSON_array_en_main = 1; -// line 662 "ParserConfig.rl" +// line 669 "ParserConfig.rl" void parseArray(ThreadContext context, ParserResult res, int p, int pe) { @@ -1638,14 +1645,14 @@ void parseArray(ThreadContext context, ParserResult res, int p, int pe) { } -// line 1642 "ParserConfig.java" +// line 1649 "ParserConfig.java" { cs = JSON_array_start; } -// line 681 "ParserConfig.rl" +// line 688 "ParserConfig.rl" -// line 1649 "ParserConfig.java" +// line 1656 "ParserConfig.java" { int _klen; int _trans = 0; @@ -1688,7 +1695,7 @@ else if ( _widec > _JSON_array_cond_keys[_mid+1] ) case 0: { _widec = 65536 + (data[p] - 0); if ( -// line 629 "ParserConfig.rl" +// line 636 "ParserConfig.rl" config.allowTrailingComma ) _widec += 65536; break; } @@ -1758,7 +1765,7 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] ) switch ( _JSON_array_actions[_acts++] ) { case 0: -// line 631 "ParserConfig.rl" +// line 638 "ParserConfig.rl" { parseValue(context, res, p, pe); if (res.result == null) { @@ -1775,13 +1782,13 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] ) } break; case 1: -// line 646 "ParserConfig.rl" +// line 653 "ParserConfig.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 1785 "ParserConfig.java" +// line 1792 "ParserConfig.java" } } } @@ -1801,7 +1808,7 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] ) break; } } -// line 682 "ParserConfig.rl" +// line 689 "ParserConfig.rl" if (cs >= JSON_array_first_final) { res.update(result, p + 1); @@ -1811,7 +1818,7 @@ else if ( _widec > _JSON_array_trans_keys[_mid+1] ) } -// line 1815 "ParserConfig.java" +// line 1822 "ParserConfig.java" private static byte[] init__JSON_object_actions_0() { return new byte [] { @@ -1988,7 +1995,7 @@ private static byte[] init__JSON_object_trans_actions_0() static final int JSON_object_en_main = 1; -// line 743 "ParserConfig.rl" +// line 750 "ParserConfig.rl" void parseObject(ThreadContext context, ParserResult res, int p, int pe) { @@ -2013,14 +2020,14 @@ void parseObject(ThreadContext context, ParserResult res, int p, int pe) { } -// line 2017 "ParserConfig.java" +// line 2024 "ParserConfig.java" { cs = JSON_object_start; } -// line 767 "ParserConfig.rl" +// line 774 "ParserConfig.rl" -// line 2024 "ParserConfig.java" +// line 2031 "ParserConfig.java" { int _klen; int _trans = 0; @@ -2063,7 +2070,7 @@ else if ( _widec > _JSON_object_cond_keys[_mid+1] ) case 0: { _widec = 65536 + (data[p] - 0); if ( -// line 696 "ParserConfig.rl" +// line 703 "ParserConfig.rl" config.allowTrailingComma ) _widec += 65536; break; } @@ -2133,7 +2140,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] ) switch ( _JSON_object_actions[_acts++] ) { case 0: -// line 698 "ParserConfig.rl" +// line 705 "ParserConfig.rl" { parseValue(context, res, p, pe); if (res.result == null) { @@ -2150,7 +2157,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] ) } break; case 1: -// line 713 "ParserConfig.rl" +// line 720 "ParserConfig.rl" { parseString(context, res, p, pe); if (res.result == null) { @@ -2168,13 +2175,13 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] ) } break; case 2: -// line 729 "ParserConfig.rl" +// line 736 "ParserConfig.rl" { p--; { p += 1; _goto_targ = 5; if (true) continue _goto;} } break; -// line 2178 "ParserConfig.java" +// line 2185 "ParserConfig.java" } } } @@ -2194,7 +2201,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] ) break; } } -// line 768 "ParserConfig.rl" +// line 775 "ParserConfig.rl" if (cs < JSON_object_first_final) { res.update(null, p + 1); @@ -2216,8 +2223,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] ) // might throw ArgumentError, we let it propagate IRubyObject klass = config.info.jsonModule.get(). callMethod(context, "deep_const_get", vKlassName); - if (klass.respondsTo("json_creatable?") && - klass.callMethod(context, "json_creatable?").isTrue()) { + if (isObjCreateable(context, klass)) { if (config.deprecatedCreateAdditions) { context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`"); } @@ -2230,7 +2236,7 @@ else if ( _widec > _JSON_object_trans_keys[_mid+1] ) } -// line 2234 "ParserConfig.java" +// line 2240 "ParserConfig.java" private static byte[] init__JSON_actions_0() { return new byte [] { @@ -2333,7 +2339,7 @@ private static byte[] init__JSON_trans_actions_0() static final int JSON_en_main = 1; -// line 822 "ParserConfig.rl" +// line 828 "ParserConfig.rl" public IRubyObject parseImplementation(ThreadContext context) { @@ -2343,16 +2349,16 @@ public IRubyObject parseImplementation(ThreadContext context) { ParserResult res = new ParserResult(); -// line 2347 "ParserConfig.java" +// line 2353 "ParserConfig.java" { cs = JSON_start; } -// line 831 "ParserConfig.rl" +// line 837 "ParserConfig.rl" p = byteList.begin(); pe = p + byteList.length(); -// line 2356 "ParserConfig.java" +// line 2362 "ParserConfig.java" { int _klen; int _trans = 0; @@ -2433,7 +2439,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] ) switch ( _JSON_actions[_acts++] ) { case 0: -// line 808 "ParserConfig.rl" +// line 814 "ParserConfig.rl" { parseValue(context, res, p, pe); if (res.result == null) { @@ -2445,7 +2451,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] ) } } break; -// line 2449 "ParserConfig.java" +// line 2455 "ParserConfig.java" } } } @@ -2465,7 +2471,7 @@ else if ( data[p] > _JSON_trans_keys[_mid+1] ) break; } } -// line 834 "ParserConfig.rl" +// line 840 "ParserConfig.rl" if (cs >= JSON_first_final && p == pe) { return result; diff --git a/java/src/json/ext/ParserConfig.rl b/java/src/json/ext/ParserConfig.rl index 0382a7c5d..8688a1016 100644 --- a/java/src/json/ext/ParserConfig.rl +++ b/java/src/json/ext/ParserConfig.rl @@ -264,6 +264,14 @@ public class ParserConfig extends RubyObject { return decimalClass.newInstance(context, context.runtime.newString(num), Block.NULL_BLOCK); } + private static boolean isObjCreateable(final ThreadContext context, IRubyObject klass) { + if (klass.respondsTo("json_creatable?")) { + return klass.callMethod(context, "json_creatable?").isTrue(); + } else { + return klass.respondsTo("json_create"); + } + } + /** * A string parsing session. * @@ -591,8 +599,7 @@ public class ParserConfig extends RubyObject { } catch (JumpException e) { } if (memoArray[1] != null) { RubyClass klass = (RubyClass) memoArray[1]; - if (klass.respondsTo("json_creatable?") && - klass.callMethod(context, "json_creatable?").isTrue()) { + if (isObjCreateable(context, klass)) { if (config.deprecatedCreateAdditions) { context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`"); } @@ -786,8 +793,7 @@ public class ParserConfig extends RubyObject { // might throw ArgumentError, we let it propagate IRubyObject klass = config.info.jsonModule.get(). callMethod(context, "deep_const_get", vKlassName); - if (klass.respondsTo("json_creatable?") && - klass.callMethod(context, "json_creatable?").isTrue()) { + if (isObjCreateable(context, klass)) { if (config.deprecatedCreateAdditions) { context.runtime.getWarnings().warn("JSON.load implicit support for `create_additions: true` is deprecated and will be removed in 3.0, use JSON.unsafe_load or explicitly pass `create_additions: true`"); } diff --git a/lib/json/common.rb b/lib/json/common.rb index 30fdbe1db..c47152e38 100644 --- a/lib/json/common.rb +++ b/lib/json/common.rb @@ -951,14 +951,3 @@ def JSON(object, *args) JSON.generate(object, args.first) end end - -# Extends any Class to include _json_creatable?_ method. -class ::Class - # Returns true if this class can be used to create an instance - # from a serialised JSON string. The class has to implement a class - # method _json_create_ that expects a hash as first parameter. The hash - # should include the required data. - def json_creatable? - respond_to?(:json_create) - end -end diff --git a/test/json/json_addition_test.rb b/test/json/json_addition_test.rb index 1eb269c2f..4d8d18687 100644 --- a/test/json/json_addition_test.rb +++ b/test/json/json_addition_test.rb @@ -44,10 +44,6 @@ def to_json(*args) end class B - def self.json_creatable? - false - end - def to_json(*args) { 'json_class' => self.class.name, @@ -56,10 +52,6 @@ def to_json(*args) end class C - def self.json_creatable? - false - end - def to_json(*args) { 'json_class' => 'JSONAdditionTest::Nix', @@ -69,7 +61,6 @@ def to_json(*args) def test_extended_json a = A.new(666) - assert A.json_creatable? json = generate(a) a_again = parse(json, :create_additions => true) assert_kind_of a.class, a_again @@ -78,7 +69,7 @@ def test_extended_json def test_extended_json_default a = A.new(666) - assert A.json_creatable? + assert A.respond_to?(:json_create) json = generate(a) a_hash = parse(json) assert_kind_of Hash, a_hash @@ -86,7 +77,6 @@ def test_extended_json_default def test_extended_json_disabled a = A.new(666) - assert A.json_creatable? json = generate(a) a_again = parse(json, :create_additions => true) assert_kind_of a.class, a_again @@ -101,14 +91,12 @@ def test_extended_json_disabled def test_extended_json_fail1 b = B.new - assert !B.json_creatable? json = generate(b) assert_equal({ "json_class"=>"JSONAdditionTest::B" }, parse(json)) end def test_extended_json_fail2 c = C.new - assert !C.json_creatable? json = generate(c) assert_raise(ArgumentError, NameError) { parse(json, :create_additions => true) } end