Skip to content

Commit a9bc48e

Browse files
authored
Merge pull request ruby#679 from casperisfine/generator-custom-base-types
Add tests for the behavior of JSON.generate with base types subclasses
2 parents 2333912 + 614921d commit a9bc48e

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

ext/json/ext/generator/generator.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,11 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
755755
VALUE key_to_s;
756756
switch(rb_type(key)) {
757757
case T_STRING:
758-
key_to_s = key;
758+
if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
759+
key_to_s = key;
760+
} else {
761+
key_to_s = rb_funcall(key, i_to_s, 0);
762+
}
759763
break;
760764
case T_SYMBOL:
761765
key_to_s = rb_sym2str(key);

test/json/json_generator_test.rb

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,72 @@ def test_to_json_called_with_state_object
536536
assert_instance_of JSON::State, argument
537537
end
538538

539+
module CustomToJSON
540+
def to_json(*)
541+
%{"#{self.class.name}#to_json"}
542+
end
543+
end
544+
545+
module CustomToS
546+
def to_s
547+
"#{self.class.name}#to_s"
548+
end
549+
end
550+
551+
class ArrayWithToJSON < Array
552+
include CustomToJSON
553+
end
554+
555+
def test_array_subclass_with_to_json
556+
assert_equal '["JSONGeneratorTest::ArrayWithToJSON#to_json"]', JSON.generate([ArrayWithToJSON.new])
557+
assert_equal '{"[]":1}', JSON.generate(ArrayWithToJSON.new => 1)
558+
end
559+
560+
class ArrayWithToS < Array
561+
include CustomToS
562+
end
563+
564+
def test_array_subclass_with_to_s
565+
assert_equal '[[]]', JSON.generate([ArrayWithToS.new])
566+
assert_equal '{"JSONGeneratorTest::ArrayWithToS#to_s":1}', JSON.generate(ArrayWithToS.new => 1)
567+
end
568+
569+
class HashWithToJSON < Hash
570+
include CustomToJSON
571+
end
572+
573+
def test_hash_subclass_with_to_json
574+
assert_equal '["JSONGeneratorTest::HashWithToJSON#to_json"]', JSON.generate([HashWithToJSON.new])
575+
assert_equal '{"{}":1}', JSON.generate(HashWithToJSON.new => 1)
576+
end
577+
578+
class HashWithToS < Hash
579+
include CustomToS
580+
end
581+
582+
def test_hash_subclass_with_to_s
583+
assert_equal '[{}]', JSON.generate([HashWithToS.new])
584+
assert_equal '{"JSONGeneratorTest::HashWithToS#to_s":1}', JSON.generate(HashWithToS.new => 1)
585+
end
586+
587+
class StringWithToJSON < String
588+
include CustomToJSON
589+
end
590+
591+
def test_string_subclass_with_to_json
592+
assert_equal '["JSONGeneratorTest::StringWithToJSON#to_json"]', JSON.generate([StringWithToJSON.new])
593+
assert_equal '{"":1}', JSON.generate(StringWithToJSON.new => 1)
594+
end
595+
596+
class StringWithToS < String
597+
include CustomToS
598+
end
599+
600+
def test_string_subclass_with_to_s
601+
assert_equal '[""]', JSON.generate([StringWithToS.new])
602+
assert_equal '{"JSONGeneratorTest::StringWithToS#to_s":1}', JSON.generate(StringWithToS.new => 1)
603+
end
604+
539605
if defined?(JSON::Ext::Generator) and RUBY_PLATFORM != "java"
540606
def test_valid_utf8_in_different_encoding
541607
utf8_string = "€™"

0 commit comments

Comments
 (0)