diff --git a/CHANGES.md b/CHANGES.md index 0895827c0..8b94c614e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,8 @@ ### Unreleased +* Fix `JSON.generate` `strict: true` mode to also restrict hash keys. + ### 2025-07-28 (2.13.2) * Improve duplicate key warning and errors to include the key name and point to the right caller. diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c index 9c6ed9304..701bb41b8 100644 --- a/ext/json/ext/generator/generator.c +++ b/ext/json/ext/generator/generator.c @@ -1041,6 +1041,9 @@ json_object_i(VALUE key, VALUE val, VALUE _arg) key_to_s = rb_sym2str(key); break; default: + if (data->state->strict) { + raise_generator_error(key, "%"PRIsVALUE" not allowed in JSON", rb_funcall(key, i_to_s, 0)); + } key_to_s = rb_convert_type(key, T_STRING, "String", "to_s"); break; } diff --git a/java/src/json/ext/Generator.java b/java/src/json/ext/Generator.java index 852509205..19b615883 100644 --- a/java/src/json/ext/Generator.java +++ b/java/src/json/ext/Generator.java @@ -544,6 +544,9 @@ private static void processEntry(ThreadContext context, Session session, OutputS } else if (keyClass == runtime.getSymbol()) { keyStr = ((RubySymbol) key).id2name(context); } else { + if (session.getState(context).strict()) { + throw Utils.buildGeneratorError(context, key, key + " not allowed in JSON").toThrowable(); + } keyStr = TypeConverter.convertToType(key, runtime.getString(), "to_s"); } diff --git a/lib/json/truffle_ruby/generator.rb b/lib/json/truffle_ruby/generator.rb index aba20068a..937cad68b 100644 --- a/lib/json/truffle_ruby/generator.rb +++ b/lib/json/truffle_ruby/generator.rb @@ -476,6 +476,10 @@ def json_transform(state) result << delim unless first result << state.indent * depth if indent + if state.strict? && !(Symbol === key || String === key) + raise GeneratorError.new("#{key.class} not allowed in JSON", value) + end + key_str = key.to_s if key_str.is_a?(String) key_json = key_str.to_json(state) diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb index 914b3f4ed..963350ea4 100755 --- a/test/json/json_generator_test.rb +++ b/test/json/json_generator_test.rb @@ -404,6 +404,18 @@ def test_json_generate_unsupported_types assert_raise JSON::GeneratorError do generate(Object.new, strict: true) end + + assert_raise JSON::GeneratorError do + generate([Object.new], strict: true) + end + + assert_raise JSON::GeneratorError do + generate({ "key" => Object.new }, strict: true) + end + + assert_raise JSON::GeneratorError do + generate({ Object.new => "value" }, strict: true) + end end def test_nesting