Manually merged from flori/json

> https://github.com/flori/json/pull/525
  > Rename escape_slash in script_safe and also escape E+2028 and E+2029

  Co-authored-by: Jean Boussier <jean.boussier@gmail.com>

  > https://github.com/flori/json/pull/454
  > Remove unnecessary initialization of create_id in JSON.parse()

  Co-authored-by: Watson <watson1978@gmail.com>
This commit is contained in:
Hiroshi SHIBATA 2023-12-01 15:51:26 +09:00
Родитель 0dfeb17296
Коммит 86045fca24
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F9CF13417264FAC2
6 изменённых файлов: 62 добавлений и 6 удалений

Просмотреть файл

@ -16,7 +16,7 @@ static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash;
i_buffer_initial_length, i_dup, i_script_safe, i_escape_slash, i_strict;
/*
* Copyright 2001-2004 Unicode, Inc.
@ -749,6 +749,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
state->script_safe = RTEST(tmp);
}
tmp = rb_hash_aref(opts, ID2SYM(i_strict));
state->strict = RTEST(tmp);
return self;
}
@ -784,6 +786,7 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_strict), state->strict ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
return result;
@ -1049,6 +1052,8 @@ static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *s
generate_json_bignum(buffer, Vstate, state, obj);
} else if (klass == rb_cFloat) {
generate_json_float(buffer, Vstate, state, obj);
} else if (state->strict) {
rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
} else if (rb_respond_to(obj, i_to_json)) {
tmp = rb_funcall(obj, i_to_json, 1, Vstate);
Check_Type(tmp, T_STRING);
@ -1423,7 +1428,7 @@ static VALUE cState_script_safe(VALUE self)
}
/*
* call-seq: script_safe=(depth)
* call-seq: script_safe=(enable)
*
* This sets whether or not the forward slashes will be escaped in
* the json output.
@ -1435,6 +1440,37 @@ static VALUE cState_script_safe_set(VALUE self, VALUE enable)
return Qnil;
}
/*
* call-seq: strict
*
* If this boolean is false, types unsupported by the JSON format will
* be serialized as strings.
* If this boolean is true, types unsupported by the JSON format will
* raise a JSON::GeneratorError.
*/
static VALUE cState_strict(VALUE self)
{
GET_STATE(self);
return state->strict ? Qtrue : Qfalse;
}
/*
* call-seq: strict=(enable)
*
* This sets whether or not to serialize types unsupported by the
* JSON format as strings.
* If this boolean is false, types unsupported by the JSON format will
* be serialized as strings.
* If this boolean is true, types unsupported by the JSON format will
* raise a JSON::GeneratorError.
*/
static VALUE cState_strict_set(VALUE self, VALUE enable)
{
GET_STATE(self);
state->strict = RTEST(enable);
return Qnil;
}
/*
* call-seq: allow_nan?
*
@ -1557,6 +1593,9 @@ void Init_generator(void)
rb_define_alias(cState, "escape_slash", "script_safe");
rb_define_alias(cState, "escape_slash?", "script_safe?");
rb_define_alias(cState, "escape_slash=", "script_safe=");
rb_define_method(cState, "strict", cState_strict, 0);
rb_define_method(cState, "strict?", cState_strict, 0);
rb_define_method(cState, "strict=", cState_strict_set, 1);
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
@ -1615,6 +1654,7 @@ void Init_generator(void)
i_max_nesting = rb_intern("max_nesting");
i_script_safe = rb_intern("script_safe");
i_escape_slash = rb_intern("escape_slash");
i_strict = rb_intern("strict");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
i_depth = rb_intern("depth");

Просмотреть файл

@ -73,6 +73,7 @@ typedef struct JSON_Generator_StateStruct {
char allow_nan;
char ascii_only;
char script_safe;
char strict;
long depth;
long buffer_initial_length;
} JSON_Generator_State;
@ -153,6 +154,8 @@ static VALUE cState_depth(VALUE self);
static VALUE cState_depth_set(VALUE self, VALUE depth);
static VALUE cState_script_safe(VALUE self);
static VALUE cState_script_safe_set(VALUE self, VALUE depth);
static VALUE cState_strict(VALUE self);
static VALUE cState_strict_set(VALUE self, VALUE strict);
static FBuffer *cState_prepare_buffer(VALUE self);
#ifndef ZALLOC
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))

Просмотреть файл

@ -3,6 +3,9 @@ require 'json/version'
require 'json/generic_object'
module JSON
NOT_SET = Object.new.freeze
private_constant :NOT_SET
class << self
# :call-seq:
# JSON[object] -> new_array or new_string
@ -608,7 +611,7 @@ module JSON
# puts File.read(path)
# Output:
# {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
def dump(obj, anIO = nil, limit = nil)
def dump(obj, anIO = nil, limit = nil, strict: NOT_SET)
if anIO and limit.nil?
anIO = anIO.to_io if anIO.respond_to?(:to_io)
unless anIO.respond_to?(:write)
@ -618,6 +621,7 @@ module JSON
end
opts = JSON.dump_default_options
opts = opts.merge(:max_nesting => limit) if limit
opts[:strict] = strict if NOT_SET != strict
result = generate(obj, opts)
if anIO
anIO.write result

Просмотреть файл

@ -1902,7 +1902,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 0;
json->create_id = rb_funcall(mJSON, i_create_id, 0);
json->create_id = Qnil;
json->object_class = Qnil;
json->array_class = Qnil;
json->decimal_class = Qnil;

Просмотреть файл

@ -797,7 +797,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 100;
json->allow_nan = 0;
json->create_additions = 0;
json->create_id = rb_funcall(mJSON, i_create_id, 0);
json->create_id = Qnil;
json->object_class = Qnil;
json->array_class = Qnil;
json->decimal_class = Qnil;

Просмотреть файл

@ -150,6 +150,7 @@ EOT
:buffer_initial_length => 1024,
:depth => 0,
:script_safe => false,
:strict => false,
:indent => " ",
:max_nesting => 100,
:object_nl => "\n",
@ -167,6 +168,7 @@ EOT
:buffer_initial_length => 1024,
:depth => 0,
:script_safe => false,
:strict => false,
:indent => "",
:max_nesting => 100,
:object_nl => "",
@ -184,6 +186,7 @@ EOT
:buffer_initial_length => 1024,
:depth => 0,
:script_safe => false,
:strict => false,
:indent => "",
:max_nesting => 0,
:object_nl => "",
@ -336,7 +339,13 @@ EOT
def test_json_generate
assert_raise JSON::GeneratorError do
assert_equal true, generate(["\xea"])
generate(["\xea"])
end
end
def test_json_generate_unsupported_types
assert_raise JSON::GeneratorError do
generate(Object.new, strict: true)
end
end