json 2.7.4 → 2.7.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +10 -0
- data/ext/json/ext/fbuffer/fbuffer.h +4 -0
- data/ext/json/ext/generator/generator.c +45 -17
- data/ext/json/ext/generator/generator.h +1 -12
- data/lib/json/common.rb +6 -1
- data/lib/json/ext/generator/state.rb +5 -5
- data/lib/json/pure/generator.rb +33 -14
- data/lib/json/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 065f3d9d7ea71adff1e29821c3cac1ebcab3ab3fa8ffc5254d4977c61b998fd4
|
4
|
+
data.tar.gz: d0ec44d829e429395f42191ac8bf91e6be4498e3c4bba37eb7fdf3ad1cfce80f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59f4e6204591c6fa2204e30ae4e663f5d5f6d89cfc44a26174da1a17cd720cd6594ad047b98933295a33f793b89e97c7952095bedda1d25f378b7a99ead84b04
|
7
|
+
data.tar.gz: 7438175fc69f92a7aa2a13b7599b417111562d9edfd94987dec4f94c37e5f2b152a6025d2f6ed2d49d246f0b0e3fe53a71038c9c59e7f826e8d3c2e09e40994a
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
### 2024-11-04 (2.7.6)
|
4
|
+
|
5
|
+
* Fix a regression in JSON.generate when dealing with Hash keys that are string subclasses, call `to_json` on them.
|
6
|
+
|
7
|
+
### 2024-10-25 (2.7.5)
|
8
|
+
|
9
|
+
* Fix a memory leak when `#to_json` methods raise an exception.
|
10
|
+
* Gracefully handle formatting configs being set to `nil` instead of `""`.
|
11
|
+
* Workaround another issue caused by conflicting versions of both `json_pure` and `json` being loaded.
|
12
|
+
|
3
13
|
### 2024-10-25 (2.7.4)
|
4
14
|
|
5
15
|
* Workaround a bug in 3.4.8 and older https://github.com/rubygems/rubygems/pull/6490.
|
@@ -403,7 +403,9 @@ static char *fstrndup(const char *ptr, unsigned long len) {
|
|
403
403
|
*/
|
404
404
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
405
405
|
{
|
406
|
-
|
406
|
+
rb_check_arity(argc, 0, 1);
|
407
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
408
|
+
return cState_partial_generate(Vstate, self, generate_json_object);
|
407
409
|
}
|
408
410
|
|
409
411
|
/*
|
@@ -415,7 +417,9 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
|
|
415
417
|
* produced JSON string output further.
|
416
418
|
*/
|
417
419
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
418
|
-
|
420
|
+
rb_check_arity(argc, 0, 1);
|
421
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
422
|
+
return cState_partial_generate(Vstate, self, generate_json_array);
|
419
423
|
}
|
420
424
|
|
421
425
|
#ifdef RUBY_INTEGER_UNIFICATION
|
@@ -426,7 +430,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
|
|
426
430
|
*/
|
427
431
|
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
428
432
|
{
|
429
|
-
|
433
|
+
rb_check_arity(argc, 0, 1);
|
434
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
435
|
+
return cState_partial_generate(Vstate, self, generate_json_integer);
|
430
436
|
}
|
431
437
|
|
432
438
|
#else
|
@@ -437,7 +443,9 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
|
|
437
443
|
*/
|
438
444
|
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
|
439
445
|
{
|
440
|
-
|
446
|
+
rb_check_arity(argc, 0, 1);
|
447
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
448
|
+
return cState_partial_generate(Vstate, self, generate_json_fixnum);
|
441
449
|
}
|
442
450
|
|
443
451
|
/*
|
@@ -447,7 +455,9 @@ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
|
|
447
455
|
*/
|
448
456
|
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
449
457
|
{
|
450
|
-
|
458
|
+
rb_check_arity(argc, 0, 1);
|
459
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
460
|
+
return cState_partial_generate(Vstate, self, generate_json_bignum);
|
451
461
|
}
|
452
462
|
#endif
|
453
463
|
|
@@ -458,7 +468,9 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
|
|
458
468
|
*/
|
459
469
|
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
|
460
470
|
{
|
461
|
-
|
471
|
+
rb_check_arity(argc, 0, 1);
|
472
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
473
|
+
return cState_partial_generate(Vstate, self, generate_json_float);
|
462
474
|
}
|
463
475
|
|
464
476
|
/*
|
@@ -481,7 +493,9 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
|
|
481
493
|
*/
|
482
494
|
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
|
483
495
|
{
|
484
|
-
|
496
|
+
rb_check_arity(argc, 0, 1);
|
497
|
+
VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
|
498
|
+
return cState_partial_generate(Vstate, self, generate_json_string);
|
485
499
|
}
|
486
500
|
|
487
501
|
/*
|
@@ -536,7 +550,8 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
|
|
536
550
|
*/
|
537
551
|
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
538
552
|
{
|
539
|
-
|
553
|
+
rb_check_arity(argc, 0, 1);
|
554
|
+
return rb_utf8_str_new("true", 4);
|
540
555
|
}
|
541
556
|
|
542
557
|
/*
|
@@ -546,7 +561,8 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
546
561
|
*/
|
547
562
|
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
548
563
|
{
|
549
|
-
|
564
|
+
rb_check_arity(argc, 0, 1);
|
565
|
+
return rb_utf8_str_new("false", 5);
|
550
566
|
}
|
551
567
|
|
552
568
|
/*
|
@@ -556,7 +572,8 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
|
|
556
572
|
*/
|
557
573
|
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
|
558
574
|
{
|
559
|
-
|
575
|
+
rb_check_arity(argc, 0, 1);
|
576
|
+
return rb_utf8_str_new("null", 4);
|
560
577
|
}
|
561
578
|
|
562
579
|
/*
|
@@ -573,7 +590,7 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
|
|
573
590
|
rb_scan_args(argc, argv, "01", &state);
|
574
591
|
Check_Type(string, T_STRING);
|
575
592
|
state = cState_from_state_s(cState, state);
|
576
|
-
return cState_partial_generate(state, string);
|
593
|
+
return cState_partial_generate(state, string, generate_json_string);
|
577
594
|
}
|
578
595
|
|
579
596
|
static void State_free(void *ptr)
|
@@ -651,7 +668,11 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
|
|
651
668
|
VALUE key_to_s;
|
652
669
|
switch(rb_type(key)) {
|
653
670
|
case T_STRING:
|
654
|
-
|
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
|
+
}
|
655
676
|
break;
|
656
677
|
case T_SYMBOL:
|
657
678
|
key_to_s = rb_sym2str(key);
|
@@ -661,7 +682,11 @@ json_object_i(VALUE key, VALUE val, VALUE _arg)
|
|
661
682
|
break;
|
662
683
|
}
|
663
684
|
|
664
|
-
|
685
|
+
if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
|
686
|
+
generate_json_string(buffer, Vstate, state, key_to_s);
|
687
|
+
} else {
|
688
|
+
generate_json(buffer, Vstate, state, key_to_s);
|
689
|
+
}
|
665
690
|
if (RB_UNLIKELY(state->space_before)) fbuffer_append(buffer, state->space_before, state->space_before_len);
|
666
691
|
fbuffer_append_char(buffer, ':');
|
667
692
|
if (RB_UNLIKELY(state->space)) fbuffer_append(buffer, state->space, state->space_len);
|
@@ -826,6 +851,7 @@ static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_
|
|
826
851
|
generate_json_bignum(buffer, Vstate, state, obj);
|
827
852
|
}
|
828
853
|
#endif
|
854
|
+
|
829
855
|
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
|
830
856
|
{
|
831
857
|
double value = RFLOAT_VALUE(obj);
|
@@ -911,13 +937,14 @@ struct generate_json_data {
|
|
911
937
|
VALUE vstate;
|
912
938
|
JSON_Generator_State *state;
|
913
939
|
VALUE obj;
|
940
|
+
void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
914
941
|
};
|
915
942
|
|
916
943
|
static VALUE generate_json_try(VALUE d)
|
917
944
|
{
|
918
945
|
struct generate_json_data *data = (struct generate_json_data *)d;
|
919
946
|
|
920
|
-
|
947
|
+
data->func(data->buffer, data->vstate, data->state, data->obj);
|
921
948
|
|
922
949
|
return Qnil;
|
923
950
|
}
|
@@ -932,7 +959,7 @@ static VALUE generate_json_rescue(VALUE d, VALUE exc)
|
|
932
959
|
return Qundef;
|
933
960
|
}
|
934
961
|
|
935
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
962
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj))
|
936
963
|
{
|
937
964
|
FBuffer *buffer = cState_prepare_buffer(self);
|
938
965
|
GET_STATE(self);
|
@@ -941,7 +968,8 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
|
941
968
|
.buffer = buffer,
|
942
969
|
.vstate = self,
|
943
970
|
.state = state,
|
944
|
-
.obj = obj
|
971
|
+
.obj = obj,
|
972
|
+
.func = func
|
945
973
|
};
|
946
974
|
rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
|
947
975
|
|
@@ -957,7 +985,7 @@ static VALUE cState_partial_generate(VALUE self, VALUE obj)
|
|
957
985
|
*/
|
958
986
|
static VALUE cState_generate(VALUE self, VALUE obj)
|
959
987
|
{
|
960
|
-
VALUE result = cState_partial_generate(self, obj);
|
988
|
+
VALUE result = cState_partial_generate(self, obj, generate_json);
|
961
989
|
GET_STATE(self);
|
962
990
|
(void)state;
|
963
991
|
return result;
|
@@ -54,17 +54,6 @@ typedef struct JSON_Generator_StateStruct {
|
|
54
54
|
JSON_Generator_State *state; \
|
55
55
|
GET_STATE_TO(self, state)
|
56
56
|
|
57
|
-
#define GENERATE_JSON(type) \
|
58
|
-
FBuffer *buffer; \
|
59
|
-
VALUE Vstate; \
|
60
|
-
JSON_Generator_State *state; \
|
61
|
-
\
|
62
|
-
rb_scan_args(argc, argv, "01", &Vstate); \
|
63
|
-
Vstate = cState_from_state_s(cState, Vstate); \
|
64
|
-
TypedData_Get_Struct(Vstate, JSON_Generator_State, &JSON_Generator_State_type, state); \
|
65
|
-
buffer = cState_prepare_buffer(Vstate); \
|
66
|
-
generate_json_##type(buffer, Vstate, state, self); \
|
67
|
-
return fbuffer_to_s(buffer)
|
68
57
|
|
69
58
|
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self);
|
70
59
|
static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self);
|
@@ -99,7 +88,7 @@ static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_
|
|
99
88
|
static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
100
89
|
static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
101
90
|
static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
|
102
|
-
static VALUE cState_partial_generate(VALUE self, VALUE obj);
|
91
|
+
static VALUE cState_partial_generate(VALUE self, VALUE obj, void (*func)(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj));
|
103
92
|
static VALUE cState_generate(VALUE self, VALUE obj);
|
104
93
|
static VALUE cState_from_state_s(VALUE self, VALUE opts);
|
105
94
|
static VALUE cState_indent(VALUE self);
|
data/lib/json/common.rb
CHANGED
@@ -219,7 +219,12 @@ module JSON
|
|
219
219
|
if opts.nil?
|
220
220
|
Parser.new(source).parse
|
221
221
|
else
|
222
|
-
|
222
|
+
# NB: The ** shouldn't be required, but we have to deal with
|
223
|
+
# different versions of the `json` and `json_pure` gems being
|
224
|
+
# loaded concurrently.
|
225
|
+
# Prior to 2.7.3, `JSON::Ext::Parser` would only take kwargs.
|
226
|
+
# Ref: https://github.com/ruby/json/issues/650
|
227
|
+
Parser.new(source, **opts).parse
|
223
228
|
end
|
224
229
|
end
|
225
230
|
|
@@ -46,15 +46,15 @@ module JSON
|
|
46
46
|
opts.each do |key, value|
|
47
47
|
case key
|
48
48
|
when :indent
|
49
|
-
self.indent = value
|
49
|
+
self.indent = value || ''
|
50
50
|
when :space
|
51
|
-
self.space = value
|
51
|
+
self.space = value || ''
|
52
52
|
when :space_before
|
53
|
-
self.space_before = value
|
53
|
+
self.space_before = value || ''
|
54
54
|
when :array_nl
|
55
|
-
self.array_nl = value
|
55
|
+
self.array_nl = value || ''
|
56
56
|
when :object_nl
|
57
|
-
self.object_nl = value
|
57
|
+
self.object_nl = value || ''
|
58
58
|
when :max_nesting
|
59
59
|
self.max_nesting = value || 0
|
60
60
|
when :depth
|
data/lib/json/pure/generator.rb
CHANGED
@@ -239,13 +239,13 @@ module JSON
|
|
239
239
|
end
|
240
240
|
|
241
241
|
# NOTE: If adding new instance variables here, check whether #generate should check them for #generate_json
|
242
|
-
@indent = opts[:indent] if opts.key?(:indent)
|
243
|
-
@space = opts[:space] if opts.key?(:space)
|
244
|
-
@space_before = opts[:space_before] if opts.key?(:space_before)
|
245
|
-
@object_nl = opts[:object_nl] if opts.key?(:object_nl)
|
246
|
-
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
|
247
|
-
@allow_nan = !!opts[:allow_nan]
|
248
|
-
@ascii_only = opts[:ascii_only]
|
242
|
+
@indent = opts[:indent] || '' if opts.key?(:indent)
|
243
|
+
@space = opts[:space] || '' if opts.key?(:space)
|
244
|
+
@space_before = opts[:space_before] || '' if opts.key?(:space_before)
|
245
|
+
@object_nl = opts[:object_nl] || '' if opts.key?(:object_nl)
|
246
|
+
@array_nl = opts[:array_nl] || '' if opts.key?(:array_nl)
|
247
|
+
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
248
|
+
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
249
249
|
@depth = opts[:depth] || 0
|
250
250
|
@buffer_initial_length ||= opts[:buffer_initial_length]
|
251
251
|
|
@@ -301,19 +301,30 @@ module JSON
|
|
301
301
|
|
302
302
|
# Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
|
303
303
|
private def generate_json(obj, buf)
|
304
|
-
|
305
|
-
|
304
|
+
klass = obj.class
|
305
|
+
if klass == Hash
|
306
306
|
buf << '{'
|
307
307
|
first = true
|
308
308
|
obj.each_pair do |k,v|
|
309
309
|
buf << ',' unless first
|
310
|
-
|
310
|
+
|
311
|
+
key_str = k.to_s
|
312
|
+
if key_str.is_a?(::String)
|
313
|
+
if key_str.class == ::String
|
314
|
+
fast_serialize_string(key_str, buf)
|
315
|
+
else
|
316
|
+
generate_json(key_str, buf)
|
317
|
+
end
|
318
|
+
else
|
319
|
+
raise TypeError, "#{k.class}#to_s returns an instance of #{key_str.class}, expected a String"
|
320
|
+
end
|
321
|
+
|
311
322
|
buf << ':'
|
312
323
|
generate_json(v, buf)
|
313
324
|
first = false
|
314
325
|
end
|
315
326
|
buf << '}'
|
316
|
-
|
327
|
+
elsif klass == Array
|
317
328
|
buf << '['
|
318
329
|
first = true
|
319
330
|
obj.each do |e|
|
@@ -322,9 +333,9 @@ module JSON
|
|
322
333
|
first = false
|
323
334
|
end
|
324
335
|
buf << ']'
|
325
|
-
|
336
|
+
elsif klass == String
|
326
337
|
fast_serialize_string(obj, buf)
|
327
|
-
|
338
|
+
elsif klass == Integer
|
328
339
|
buf << obj.to_s
|
329
340
|
else
|
330
341
|
# Note: Float is handled this way since Float#to_s is slow anyway
|
@@ -414,7 +425,15 @@ module JSON
|
|
414
425
|
each { |key, value|
|
415
426
|
result << delim unless first
|
416
427
|
result << state.indent * depth if indent
|
417
|
-
|
428
|
+
|
429
|
+
key_str = key.to_s
|
430
|
+
key_json = if key_str.is_a?(::String)
|
431
|
+
key_str = key_str.to_json(state)
|
432
|
+
else
|
433
|
+
raise TypeError, "#{key.class}#to_s returns an instance of #{key_str.class}, expected a String"
|
434
|
+
end
|
435
|
+
|
436
|
+
result = +"#{result}#{key_json}#{state.space_before}:#{state.space}"
|
418
437
|
if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
|
419
438
|
raise GeneratorError, "#{value.class} not allowed in JSON"
|
420
439
|
elsif value.respond_to?(:to_json)
|
data/lib/json/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.
|
4
|
+
version: 2.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Frank
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: This is a JSON implementation as a Ruby extension in C.
|
14
14
|
email: flori@ping.de
|