summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2024-09-05 00:47:06 +0900
committerGitHub <noreply@github.com>2024-09-04 08:47:06 -0700
commit4eb51dfc9e67683a1a03fdf302d5ddd95cad716a (patch)
tree69aae24326783b834d5660949ca8c0408f9e18ab
parentef084cc8f4958c1b6e4ead99136631bef6d8ddba (diff)
Merge JSON 2.7.2 for Ruby 3.3 (#11541)
Merge JSON 2.7.2
-rw-r--r--ext/json/generator/generator.c42
-rw-r--r--ext/json/lib/json/add/ostruct.rb7
-rw-r--r--ext/json/lib/json/common.rb3
-rw-r--r--ext/json/lib/json/generic_object.rb8
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--test/json/json_addition_test.rb2
-rw-r--r--test/json/json_generic_object_test.rb2
-rw-r--r--test/json/json_parser_test.rb71
8 files changed, 90 insertions, 47 deletions
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index a71acfbb76..6d78284bc4 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -867,7 +867,7 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
if (klass == rb_cString) {
key_to_s = key;
} else if (klass == rb_cSymbol) {
- key_to_s = rb_id2str(SYM2ID(key));
+ key_to_s = rb_sym2str(key);
} else {
key_to_s = rb_funcall(key, i_to_s, 0);
}
@@ -892,7 +892,6 @@ static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
struct hash_foreach_arg arg;
if (max_nesting != 0 && depth > max_nesting) {
- fbuffer_free(buffer);
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
}
fbuffer_append_char(buffer, '{');
@@ -927,7 +926,6 @@ static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
long depth = ++state->depth;
int i, j;
if (max_nesting != 0 && depth > max_nesting) {
- fbuffer_free(buffer);
rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
}
fbuffer_append_char(buffer, '[');
@@ -1020,10 +1018,8 @@ static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_St
VALUE tmp = rb_funcall(obj, i_to_s, 0);
if (!allow_nan) {
if (isinf(value)) {
- fbuffer_free(buffer);
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
} else if (isnan(value)) {
- fbuffer_free(buffer);
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
}
}
@@ -1096,11 +1092,45 @@ static FBuffer *cState_prepare_buffer(VALUE self)
return buffer;
}
+struct generate_json_data {
+ FBuffer *buffer;
+ VALUE vstate;
+ JSON_Generator_State *state;
+ VALUE obj;
+};
+
+static VALUE generate_json_try(VALUE d)
+{
+ struct generate_json_data *data = (struct generate_json_data *)d;
+
+ generate_json(data->buffer, data->vstate, data->state, data->obj);
+
+ return Qnil;
+}
+
+static VALUE generate_json_rescue(VALUE d, VALUE exc)
+{
+ struct generate_json_data *data = (struct generate_json_data *)d;
+ fbuffer_free(data->buffer);
+
+ rb_exc_raise(exc);
+
+ return Qundef;
+}
+
static VALUE cState_partial_generate(VALUE self, VALUE obj)
{
FBuffer *buffer = cState_prepare_buffer(self);
GET_STATE(self);
- generate_json(buffer, self, state, obj);
+
+ struct generate_json_data data = {
+ .buffer = buffer,
+ .vstate = self,
+ .state = state,
+ .obj = obj
+ };
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
+
return fbuffer_to_s(buffer);
}
diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb
index 498de17178..1e6f408248 100644
--- a/ext/json/lib/json/add/ostruct.rb
+++ b/ext/json/lib/json/add/ostruct.rb
@@ -2,7 +2,10 @@
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
-require 'ostruct'
+begin
+ require 'ostruct'
+rescue LoadError
+end
class OpenStruct
@@ -48,4 +51,4 @@ class OpenStruct
def to_json(*args)
as_json.to_json(*args)
end
-end
+end if defined?(::OpenStruct)
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 090066012d..95098d3bb4 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -1,8 +1,9 @@
#frozen_string_literal: false
require 'json/version'
-require 'json/generic_object'
module JSON
+ autoload :GenericObject, 'json/generic_object'
+
NOT_SET = Object.new.freeze
private_constant :NOT_SET
diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb
index 108309db26..56efda6495 100644
--- a/ext/json/lib/json/generic_object.rb
+++ b/ext/json/lib/json/generic_object.rb
@@ -1,5 +1,9 @@
#frozen_string_literal: false
-require 'ostruct'
+begin
+ require 'ostruct'
+rescue LoadError
+ warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`."
+end
module JSON
class GenericObject < OpenStruct
@@ -67,5 +71,5 @@ module JSON
def to_json(*a)
as_json.to_json(*a)
end
- end
+ end if defined?(::OpenStruct)
end
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index b43ceecdcd..836f47edf4 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module JSON
# JSON version
- VERSION = '2.7.1'
+ VERSION = '2.7.2'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/test/json/json_addition_test.rb b/test/json/json_addition_test.rb
index 2877bef7d8..3a7a58176a 100644
--- a/test/json/json_addition_test.rb
+++ b/test/json/json_addition_test.rb
@@ -190,7 +190,7 @@ class JSONAdditionTest < Test::Unit::TestCase
# XXX this won't work; o.foo = { :bar => true }
o.foo = { 'bar' => true }
assert_equal o, parse(JSON(o), :create_additions => true)
- end
+ end if defined?(::OpenStruct)
def test_set
s = Set.new([:a, :b, :c, :a])
diff --git a/test/json/json_generic_object_test.rb b/test/json/json_generic_object_test.rb
index c4d391208c..d6d7e30816 100644
--- a/test/json/json_generic_object_test.rb
+++ b/test/json/json_generic_object_test.rb
@@ -79,4 +79,4 @@ class JSONGenericObjectTest < Test::Unit::TestCase
ensure
JSON::GenericObject.json_creatable = false
end
-end
+end if defined?(JSON::GenericObject)
diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb
index cc9a74a95b..49c7c8565d 100644
--- a/test/json/json_parser_test.rb
+++ b/test/json/json_parser_test.rb
@@ -3,7 +3,10 @@
require_relative 'test_helper'
require 'stringio'
require 'tempfile'
-require 'ostruct'
+begin
+ require 'ostruct'
+rescue LoadError
+end
begin
require 'bigdecimal'
rescue LoadError
@@ -412,21 +415,6 @@ EOT
end
end
- class SubOpenStruct < OpenStruct
- def [](k)
- __send__(k)
- end
-
- def []=(k, v)
- @item_set = true
- __send__("#{k}=", v)
- end
-
- def item_set?
- @item_set
- end
- end
-
def test_parse_object_custom_hash_derived_class
res = parse('{"foo":"bar"}', :object_class => SubHash)
assert_equal({"foo" => "bar"}, res)
@@ -434,24 +422,41 @@ EOT
assert res.item_set?
end
- def test_parse_object_custom_non_hash_derived_class
- res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
- assert_equal "bar", res.foo
- assert_equal(SubOpenStruct, res.class)
- assert res.item_set?
- end
+ if defined?(::OpenStruct)
+ class SubOpenStruct < OpenStruct
+ def [](k)
+ __send__(k)
+ end
- def test_parse_generic_object
- res = parse(
- '{"foo":"bar", "baz":{}}',
- :object_class => JSON::GenericObject
- )
- assert_equal(JSON::GenericObject, res.class)
- assert_equal "bar", res.foo
- assert_equal "bar", res["foo"]
- assert_equal "bar", res[:foo]
- assert_equal "bar", res.to_hash[:foo]
- assert_equal(JSON::GenericObject, res.baz.class)
+ def []=(k, v)
+ @item_set = true
+ __send__("#{k}=", v)
+ end
+
+ def item_set?
+ @item_set
+ end
+ end
+
+ def test_parse_object_custom_non_hash_derived_class
+ res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
+ assert_equal "bar", res.foo
+ assert_equal(SubOpenStruct, res.class)
+ assert res.item_set?
+ end
+
+ def test_parse_generic_object
+ res = parse(
+ '{"foo":"bar", "baz":{}}',
+ :object_class => JSON::GenericObject
+ )
+ assert_equal(JSON::GenericObject, res.class)
+ assert_equal "bar", res.foo
+ assert_equal "bar", res["foo"]
+ assert_equal "bar", res[:foo]
+ assert_equal "bar", res.to_hash[:foo]
+ assert_equal(JSON::GenericObject, res.baz.class)
+ end
end
def test_generate_core_subclasses_with_new_to_json