diff --git a/CHANGES.md b/CHANGES.md index b2273765..202bf2d5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,15 @@ # Changes +### 2025-02-10 (2.10.1) + +* Fix a compatibility issue with `MultiJson.dump(obj, pretty: true)`: `no implicit conversion of false into Proc (TypeError)`. + ### 2025-02-10 (2.10.0) * `strict: true` now accept symbols as values. Previously they'd only be accepted as hash keys. * The C extension Parser has been entirely reimplemented from scratch. * Introduced `JSON::Coder` as a new API allowing to customize how non native types are serialized in a non-global way. +* Introduced `JSON::Fragment` to allow assembling cached fragments in a safe way. * The Java implementation of the generator received many optimizations. ### 2024-12-18 (2.9.1) diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c index bb390d1b..08338853 100644 --- a/ext/json/ext/generator/generator.c +++ b/ext/json/ext/generator/generator.c @@ -1626,7 +1626,7 @@ static int configure_state_i(VALUE key, VALUE val, VALUE _arg) else if (key == sym_script_safe) { state->script_safe = RTEST(val); } else if (key == sym_escape_slash) { state->script_safe = RTEST(val); } else if (key == sym_strict) { state->strict = RTEST(val); } - else if (key == sym_as_json) { state->as_json = rb_convert_type(val, T_DATA, "Proc", "to_proc"); } + else if (key == sym_as_json) { state->as_json = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse; } return ST_CONTINUE; } diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java index dc07ffa9..524d6b05 100644 --- a/java/src/json/ext/GeneratorState.java +++ b/java/src/json/ext/GeneratorState.java @@ -368,9 +368,12 @@ public IRubyObject as_json_get(ThreadContext context) { } @JRubyMethod(name="as_json=") - public IRubyObject as_json_set(ThreadContext context, - IRubyObject asJSON) { - this.asJSON = (RubyProc)TypeConverter.convertToType(asJSON, context.getRuntime().getProc(), "to_proc"); + public IRubyObject as_json_set(ThreadContext context, IRubyObject asJSON) { + if (asJSON.isNil() || asJSON == context.getRuntime().getFalse()) { + this.asJSON = null; + } else { + this.asJSON = (RubyProc)TypeConverter.convertToType(asJSON, context.getRuntime().getProc(), "to_proc"); + } return asJSON; } diff --git a/java/src/json/ext/OptionsReader.java b/java/src/json/ext/OptionsReader.java index 985bc018..c372eb1a 100644 --- a/java/src/json/ext/OptionsReader.java +++ b/java/src/json/ext/OptionsReader.java @@ -115,7 +115,7 @@ public RubyHash getHash(String key) { RubyProc getProc(String key) { IRubyObject value = get(key); - if (value == null) return null; + if (value == null || value.isNil() || value == runtime.getFalse()) return null; return (RubyProc)TypeConverter.convertToType(value, runtime.getProc(), "to_proc"); } } diff --git a/lib/json/truffle_ruby/generator.rb b/lib/json/truffle_ruby/generator.rb index 37a980fe..bf6289f1 100644 --- a/lib/json/truffle_ruby/generator.rb +++ b/lib/json/truffle_ruby/generator.rb @@ -258,7 +258,7 @@ def configure(opts) @object_nl = opts[:object_nl] || '' if opts.key?(:object_nl) @array_nl = opts[:array_nl] || '' if opts.key?(:array_nl) @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan) - @as_json = opts[:as_json].to_proc if opts.key?(:as_json) + @as_json = opts[:as_json].to_proc if opts[:as_json] @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only) @depth = opts[:depth] || 0 @buffer_initial_length ||= opts[:buffer_initial_length] diff --git a/lib/json/version.rb b/lib/json/version.rb index e2297c1a..65bcb976 100644 --- a/lib/json/version.rb +++ b/lib/json/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module JSON - VERSION = '2.10.0' + VERSION = '2.10.1' end diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index 942802d6..c67cd334 100755 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -399,6 +399,11 @@ def test_hash_likeness_set_string assert_equal :bar, state_hash[:foo] end + def test_json_state_to_h_roundtrip + state = JSON.state.new + assert_equal state.to_h, JSON.state.new(state.to_h).to_h + end + def test_json_generate assert_raise JSON::GeneratorError do generate(["\xea"])