Compare commits

...
Sign in to create a new pull request.

13 commits

Author SHA1 Message Date
Mamoru TASAKA
3d429ea59d 2.18.0 2026-01-09 20:40:51 +09:00
Mamoru TASAKA
af402fae1d fix release 2025-10-07 21:00:37 +09:00
Mamoru TASAKA
5dd12f04eb 2.15.1 2025-10-07 20:58:41 +09:00
Mamoru TASAKA
12253f7294 2.15.0 2025-09-26 09:55:07 +09:00
Mamoru TASAKA
c8995f0291 2.13.2 2025-07-31 20:57:36 +09:00
Fedora Release Engineering
c4693bbb66 Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild 2025-07-25 12:31:45 +00:00
Mamoru TASAKA
745cbb15b1 2.12.2 2025-05-28 09:52:23 +09:00
Mamoru TASAKA
3cc8a57e37 2.12.0 2025-05-17 09:51:07 +09:00
Mamoru TASAKA
bd335bb9c7 2.11.3 2025-04-30 10:48:14 +09:00
Mamoru TASAKA
a6f8d01189 2.10.2 2025-03-13 10:12:57 +09:00
Mamoru TASAKA
079d8c64bb 2.10.1 2025-02-12 16:07:09 +09:00
Fedora Release Engineering
51a7e0e68e Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild 2025-01-18 23:29:21 +00:00
Mamoru TASAKA
1b3433d4bc Rebuild for https://fedoraproject.org/wiki/Changes/Ruby_3.4 2025-01-08 08:16:56 +09:00
3 changed files with 40 additions and 200 deletions

View file

@ -1,196 +0,0 @@
From 045e58d8310890c43bf48a3b9ed6062b781b52c2 Mon Sep 17 00:00:00 2001
From: Jean Boussier <jean.boussier@gmail.com>
Date: Thu, 31 Oct 2024 08:52:19 +0100
Subject: [PATCH] JSON.generate: call to_json on String subclasses
Fix: https://github.com/ruby/json/issues/667
This is yet another behavior on which the various implementations
differed, but the C implementation used to call `to_json` on String
subclasses used as keys.
This was optimized out in e125072130229e54a651f7b11d7d5a782ae7fb65
but there is an Active Support test case for it, so it's best to
make all 3 implementation respect this behavior.
---
CHANGES.md | 2 ++
ext/json/ext/fbuffer/fbuffer.h | 4 +++
ext/json/ext/generator/generator.c | 6 +++-
java/src/json/ext/Generator.java | 9 +++++-
lib/json/pure/generator.rb | 33 +++++++++++++++-----
test/json/json_generator_test.rb | 50 ++++++++++++++++++++++++++++++
6 files changed, 95 insertions(+), 9 deletions(-)
diff --git a/CHANGES.md b/CHANGES.md
index 667958ea..1cab01ee 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,7 @@
# Changes
+* Fix a regression in JSON.generate when dealing with Hash keys that are string subclasses, call `to_json` on them.
+
### 2024-10-25 (2.7.5)
* Fix a memory leak when `#to_json` methods raise an exception.
diff --git a/ext/json/ext/fbuffer/fbuffer.h b/ext/json/ext/fbuffer/fbuffer.h
index 76bd6ce1..4c62aa36 100644
--- a/ext/json/ext/fbuffer/fbuffer.h
+++ b/ext/json/ext/fbuffer/fbuffer.h
@@ -36,6 +36,10 @@ static VALUE fbuffer_to_s(FBuffer *fb);
#define RB_UNLIKELY(expr) expr
#endif
+#ifndef RB_LIKELY
+#define RB_LIKELY(expr) expr
+#endif
+
static FBuffer *fbuffer_alloc(unsigned long initial_length)
{
FBuffer *fb;
diff --git a/ext/json/ext/generator/generator.c b/ext/json/ext/generator/generator.c
index ca48e0f1..ca9f1a9c 100644
--- a/ext/json/ext/generator/generator.c
+++ b/ext/json/ext/generator/generator.c
@@ -678,7 +678,11 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
break;
}
- generate_json_string(buffer, Vstate, state, key_to_s);
+ if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
+ generate_json_string(buffer, Vstate, state, key_to_s);
+ } else {
+ generate_json(buffer, Vstate, state, key_to_s);
+ }
if (RB_UNLIKELY(state->space_before)) fbuffer_append(buffer, state->space_before, state->space_before_len);
fbuffer_append_char(buffer, ':');
if (RB_UNLIKELY(state->space)) fbuffer_append(buffer, state->space, state->space_len);
diff --git a/lib/json/pure/generator.rb b/lib/json/pure/generator.rb
index 516ee287..0a563813 100644
--- a/lib/json/pure/generator.rb
+++ b/lib/json/pure/generator.rb
@@ -301,19 +301,30 @@ def generate(obj)
# Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
private def generate_json(obj, buf)
- case obj
- when Hash
+ klass = obj.class
+ if klass == Hash
buf << '{'
first = true
obj.each_pair do |k,v|
buf << ',' unless first
- fast_serialize_string(k.to_s, buf)
+
+ key_str = k.to_s
+ if key_str.is_a?(::String)
+ if key_str.class == ::String
+ fast_serialize_string(key_str, buf)
+ else
+ generate_json(key_str, buf)
+ end
+ else
+ raise TypeError, "#{k.class}#to_s returns an instance of #{key_str.class}, expected a String"
+ end
+
buf << ':'
generate_json(v, buf)
first = false
end
buf << '}'
- when Array
+ elsif klass == Array
buf << '['
first = true
obj.each do |e|
@@ -322,9 +333,9 @@ def generate(obj)
first = false
end
buf << ']'
- when String
+ elsif klass == String
fast_serialize_string(obj, buf)
- when Integer
+ elsif klass == Integer
buf << obj.to_s
else
# Note: Float is handled this way since Float#to_s is slow anyway
@@ -414,7 +425,15 @@ def json_transform(state)
each { |key, value|
result << delim unless first
result << state.indent * depth if indent
- result = +"#{result}#{key.to_s.to_json(state)}#{state.space_before}:#{state.space}"
+
+ key_str = key.to_s
+ key_json = if key_str.is_a?(::String)
+ key_str = key_str.to_json(state)
+ else
+ raise TypeError, "#{key.class}#to_s returns an instance of #{key_str.class}, expected a String"
+ end
+
+ result = +"#{result}#{key_json}#{state.space_before}:#{state.space}"
if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
raise GeneratorError, "#{value.class} not allowed in JSON"
elsif value.respond_to?(:to_json)
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index a83d730d..8e76bec3 100755
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -479,6 +479,56 @@ def test_invalid_encoding_string
end
end
+ class MyCustomString < String
+ def to_json(_state = nil)
+ '"my_custom_key"'
+ end
+
+ def to_s
+ self
+ end
+ end
+
+ def test_string_subclass_as_keys
+ # Ref: https://github.com/ruby/json/issues/667
+ # if key.to_s doesn't return a bare string, we call `to_json` on it.
+ key = MyCustomString.new("won't be used")
+ assert_equal '{"my_custom_key":1}', JSON.generate(key => 1)
+ end
+
+ class FakeString
+ def to_json(_state = nil)
+ raise "Shouldn't be called"
+ end
+
+ def to_s
+ self
+ end
+ end
+
+ def test_custom_object_as_keys
+ key = FakeString.new
+ error = assert_raise(TypeError) do
+ JSON.generate(key => 1)
+ end
+ assert_match "FakeString", error.message
+ end
+
+ def test_to_json_called_with_state_object
+ object = Object.new
+ called = false
+ argument = nil
+ object.singleton_class.define_method(:to_json) do |state|
+ called = true
+ argument = state
+ "<hello>"
+ end
+
+ assert_equal "<hello>", JSON.dump(object)
+ assert called, "#to_json wasn't called"
+ assert_instance_of JSON::State, argument
+ end
+
if defined?(JSON::Ext::Generator) and RUBY_PLATFORM != "java"
def test_valid_utf8_in_different_encoding
utf8_string = "€™"

View file

@ -1,8 +1,8 @@
%global gem_name json
%global pkg_version_num 2.9.1
%global pkg_version_num 2.18.0
%dnl %global pkg_version_alpha
%global gem_version %{pkg_version_num}%{?pkg_version_alpha:.%pkg_version_alpha}
%global gem_version() %{pkg_version_num}%{?pkg_version_alpha:.%pkg_version_alpha}
Name: rubygem-%{gem_name}
Version: %{pkg_version_num}%{?pkg_version_alpha:~%pkg_version_alpha}
@ -136,6 +136,42 @@ popd
%changelog
* Fri Jan 09 2026 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.18.0-1
- 2.18.0
* Tue Oct 07 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.15.1-1
- 2.15.1
* Thu Sep 25 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.15.0-1
- 2.15.0
* Thu Jul 31 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.13.2-1
- 2.13.2
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 2.12.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Tue May 27 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.12.2-1
- 2.12.2
* Fri May 16 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.12.0-1
- 2.12.0
* Tue Apr 29 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.11.3-1
- 2.11.3
* Wed Mar 12 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.10.2-1
- 2.10.2
* Tue Feb 11 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.10.1-1
- 2.10.1
* Sat Jan 18 2025 Fedora Release Engineering <releng@fedoraproject.org> - 2.9.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
* Tue Jan 07 2025 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.9.1-2
- Rebuild for https://fedoraproject.org/wiki/Changes/Ruby_3.4
* Thu Dec 19 2024 Mamoru TASAKA <mtasaka@fedoraproject.org> - 2.9.1-1
- 2.9.1

View file

@ -1,2 +1,2 @@
SHA512 (json-2.9.1.gem) = 96b7de437f3bdc93f0de2ff04e1f666008a2debb96e0c55f64de79ecb111a786601436ef44e7b7f89125d1d7eb13c31680f45a5002826c99d2b378bc4f465699
SHA512 (rubygem-json-2.9.1-missing-files.tar.gz) = ee7fa79da9e90a79c62e5eb0895caedf7f76b863842adf0cc92bde7730bd0ae8f7bd421ed7c583c910f1f8ba414126955956beea39d7e47a6e42568adb41f056
SHA512 (json-2.18.0.gem) = 02b25232a78f0da5bab6db01771385bb0bcefbd6f182314474ca23b61af6a2ec0a66b160ec7a9a3d6c75ccd3a57da08897400fe2673f5cca6a650e133029b884
SHA512 (rubygem-json-2.18.0-missing-files.tar.gz) = 73453c9e4312ede95f5a3a794cf86f8d138be5425e40e410326fab3592c22710837e5e2c118c4e947466042e6d300a0bd7cb652a3325bb3b9e617705356411da