diff --git a/java/src/json/ext/GeneratorState.java b/java/src/json/ext/GeneratorState.java index dabc9e255..3fdf4f276 100644 --- a/java/src/json/ext/GeneratorState.java +++ b/java/src/json/ext/GeneratorState.java @@ -545,43 +545,41 @@ public IRubyObject _configure(ThreadContext context, IRubyObject vOpts) { checkFrozen(); OptionsReader opts = new OptionsReader(context, vOpts); - ByteList indent = opts.getString("indent"); - if (indent != null) this.indent = indent; - - ByteList space = opts.getString("space"); - if (space != null) this.space = space; - - ByteList spaceBefore = opts.getString("space_before"); - if (spaceBefore != null) this.spaceBefore = spaceBefore; - - ByteList arrayNl = opts.getString("array_nl"); - if (arrayNl != null) this.arrayNl = arrayNl; - - this.asJSON = opts.getProc("as_json"); - - ByteList objectNl = opts.getString("object_nl"); - if (objectNl != null) this.objectNl = objectNl; - - maxNesting = opts.getInt("max_nesting", DEFAULT_MAX_NESTING); - allowNaN = opts.getBool("allow_nan", DEFAULT_ALLOW_NAN); - asciiOnly = opts.getBool("ascii_only", DEFAULT_ASCII_ONLY); - scriptSafe = opts.getBool("script_safe", DEFAULT_SCRIPT_SAFE); - strict = opts.getBool("strict", DEFAULT_STRICT); - bufferInitialLength = opts.getInt("buffer_initial_length", DEFAULT_BUFFER_INITIAL_LENGTH); - - depth = opts.getInt("depth", 0); + this.indent = stringConfig(opts, "indent", this.indent); + this.space = stringConfig(opts, "space", this.space); + this.spaceBefore = stringConfig(opts, "space_before", this.spaceBefore); + this.arrayNl = stringConfig(opts, "array_nl", this.arrayNl); + this.objectNl = stringConfig(opts, "object_nl", this.objectNl); + + if (opts.hasKey("as_json")) this.asJSON = opts.getProc("as_json"); + + maxNesting = opts.getInt("max_nesting", maxNesting); + allowNaN = opts.getBool("allow_nan", allowNaN); + asciiOnly = opts.getBool("ascii_only", asciiOnly); + scriptSafe = opts.getBool("script_safe", scriptSafe); + strict = opts.getBool("strict", strict); + bufferInitialLength = opts.getInt("buffer_initial_length", bufferInitialLength); + + depth = opts.getInt("depth", depth); if (depth < 0) { throw context.runtime.newArgumentError("depth must be >= 0 (got: " + depth + ")"); } - this.allowDuplicateKey = opts.getBool("allow_duplicate_key", false); + this.allowDuplicateKey = opts.getBool("allow_duplicate_key", allowDuplicateKey); - sortKeys = normalizeSortKeys(context, opts.get("sort_keys")); + if (opts.hasKey("sort_keys")) sortKeys = normalizeSortKeys(context, opts.get("sort_keys")); opts.ensureEmpty(); return this; } + // A falsy value writes the empty string, as string_config() does in the C extension. + private static ByteList stringConfig(OptionsReader opts, String key, ByteList current) { + if (!opts.hasKey(key)) return current; + ByteList value = opts.getString(key); + return value == null ? ByteList.EMPTY_BYTELIST : value; + } + /** * State#to_h() * diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index 1f4b5d949..1b2197735 100755 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -539,18 +539,32 @@ def test_configure_keeps_the_layout_of_a_pretty_state end def test_configure_only_writes_the_other_options_it_is_given - omit 'JRuby resets the non-string options' if RUBY_ENGINE == 'jruby' - state = JSON.state.new(max_nesting: 3, allow_nan: true, ascii_only: true, script_safe: true) + state = JSON.state.new(max_nesting: 3, allow_nan: true, ascii_only: true, script_safe: true, + strict: true, buffer_initial_length: 32) state.configure(indent: '1') assert_equal '1', state.indent assert_equal 3, state.max_nesting assert_equal true, state.allow_nan? assert_equal true, state.ascii_only? assert_equal true, state.script_safe? + assert_equal true, state.strict? + assert_equal 32, state.buffer_initial_length + end + + def test_configure_keeps_sort_keys + state = JSON.state.new(sort_keys: true) + state.configure(depth: 0) + assert_equal '{"a":2,"b":1}', state.generate({ 'b' => 1, 'a' => 2 }) + end + + def test_configure_keeps_as_json + as_json = ->(object, _is_key) { object.to_s } + state = JSON.state.new(strict: true, as_json: as_json) + state.configure(depth: 0) + assert_equal as_json, state.as_json end def test_configure_writes_a_string_option_given_as_nil - omit 'JRuby keeps the previous value for an explicit nil' if RUBY_ENGINE == 'jruby' state = JSON.state.new(indent: '1', space: '2') state.configure(indent: nil) assert_equal '', state.indent