Skip to content

Commit 987f59d

Browse files
committed
Merge pull request #679 from casperisfine/generator-custom-base-types
Add tests for the behavior of JSON.generate with base types subclasses
1 parent e08d222 commit 987f59d

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
@@ -668,7 +668,11 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
668668
VALUE key_to_s;
669669
switch(rb_type(key)) {
670670
case T_STRING:
671-
key_to_s = key;
671+
if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
672+
key_to_s = key;
673+
} else {
674+
key_to_s = rb_funcall(key, i_to_s, 0);
675+
}
672676
break;
673677
case T_SYMBOL:
674678
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
@@ -529,6 +529,72 @@ def test_to_json_called_with_state_object
529529
assert_instance_of JSON::State, argument
530530
end
531531

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

0 commit comments

Comments
 (0)