json 2.9.1 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/json.gemspec CHANGED
@@ -11,14 +11,13 @@ spec = Gem::Specification.new do |s|
11
11
  s.version = version
12
12
 
13
13
  s.summary = "JSON Implementation for Ruby"
14
- s.homepage = "https://ruby.github.io/json"
14
+ s.homepage = "https://github.com/ruby/json"
15
15
  s.metadata = {
16
16
  'bug_tracker_uri' => 'https://github.com/ruby/json/issues',
17
17
  'changelog_uri' => 'https://github.com/ruby/json/blob/master/CHANGES.md',
18
- 'documentation_uri' => 'https://ruby.github.io/json/doc/index.html',
18
+ 'documentation_uri' => 'https://docs.ruby-lang.org/en/master/JSON.html',
19
19
  'homepage_uri' => s.homepage,
20
20
  'source_code_uri' => 'https://github.com/ruby/json',
21
- 'wiki_uri' => 'https://github.com/ruby/json/wiki'
22
21
  }
23
22
 
24
23
  s.required_ruby_version = Gem::Requirement.new(">= 2.7")
@@ -53,7 +52,7 @@ spec = Gem::Specification.new do |s|
53
52
  s.files += Dir["lib/json/ext/**/*.jar"]
54
53
  else
55
54
  s.extensions = Dir["ext/json/**/extconf.rb"]
56
- s.files += Dir["ext/json/**/*.{c,h,rl}"]
55
+ s.files += Dir["ext/json/**/*.{c,h}"]
57
56
  end
58
57
  end
59
58
 
@@ -36,8 +36,13 @@ class Symbol
36
36
  #
37
37
  # # {"json_class":"Symbol","s":"foo"}
38
38
  #
39
- def to_json(*a)
40
- as_json.to_json(*a)
39
+ def to_json(state = nil, *a)
40
+ state = ::JSON::State.from_state(state)
41
+ if state.strict?
42
+ super
43
+ else
44
+ as_json.to_json(state, *a)
45
+ end
41
46
  end
42
47
 
43
48
  # See #as_json.
data/lib/json/common.rb CHANGED
@@ -167,6 +167,30 @@ module JSON
167
167
  # system. Usually this means that the iconv library is not installed.
168
168
  class MissingUnicodeSupport < JSONError; end
169
169
 
170
+ # Fragment of JSON document that is to be included as is:
171
+ # fragment = JSON::Fragment.new("[1, 2, 3]")
172
+ # JSON.generate({ count: 3, items: fragments })
173
+ #
174
+ # This allows to easily assemble multiple JSON fragments that have
175
+ # been persisted somewhere without having to parse them nor resorting
176
+ # to string interpolation.
177
+ #
178
+ # Note: no validation is performed on the provided string. It is the
179
+ # responsability of the caller to ensure the string contains valid JSON.
180
+ Fragment = Struct.new(:json) do
181
+ def initialize(json)
182
+ unless string = String.try_convert(json)
183
+ raise TypeError, " no implicit conversion of #{json.class} into String"
184
+ end
185
+
186
+ super(string)
187
+ end
188
+
189
+ def to_json(state = nil, *)
190
+ json
191
+ end
192
+ end
193
+
170
194
  module_function
171
195
 
172
196
  # :call-seq:
@@ -232,12 +256,13 @@ module JSON
232
256
  # - Option +max_nesting+, if not provided, defaults to +false+,
233
257
  # which disables checking for nesting depth.
234
258
  # - Option +allow_nan+, if not provided, defaults to +true+.
235
- def parse!(source, opts = {})
236
- opts = {
259
+ def parse!(source, opts = nil)
260
+ options = {
237
261
  :max_nesting => false,
238
262
  :allow_nan => true
239
- }.merge(opts)
240
- Parser.new(source, **(opts||{})).parse
263
+ }
264
+ options.merge!(opts) if opts
265
+ Parser.new(source, options).parse
241
266
  end
242
267
 
243
268
  # :call-seq:
@@ -258,7 +283,7 @@ module JSON
258
283
  # JSON.parse!(File.read(path, opts))
259
284
  #
260
285
  # See method #parse!
261
- def load_file!(filespec, opts = {})
286
+ def load_file!(filespec, opts = nil)
262
287
  parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
263
288
  end
264
289
 
@@ -818,11 +843,7 @@ module JSON
818
843
  opts = merge_dump_options(opts, **kwargs) if kwargs
819
844
 
820
845
  begin
821
- if State === opts
822
- opts.generate(obj, anIO)
823
- else
824
- State.generate(obj, opts, anIO)
825
- end
846
+ State.generate(obj, opts, anIO)
826
847
  rescue JSON::NestingError
827
848
  raise ArgumentError, "exceed depth limit"
828
849
  end
@@ -841,6 +862,82 @@ module JSON
841
862
  class << self
842
863
  private :merge_dump_options
843
864
  end
865
+
866
+ # JSON::Coder holds a parser and generator configuration.
867
+ #
868
+ # module MyApp
869
+ # JSONC_CODER = JSON::Coder.new(
870
+ # allow_trailing_comma: true
871
+ # )
872
+ # end
873
+ #
874
+ # MyApp::JSONC_CODER.load(document)
875
+ #
876
+ class Coder
877
+ # :call-seq:
878
+ # JSON.new(options = nil, &block)
879
+ #
880
+ # Argument +options+, if given, contains a \Hash of options for both parsing and generating.
881
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
882
+ #
883
+ # For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
884
+ # encoutered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
885
+ # \JSON counterpart:
886
+ #
887
+ # module MyApp
888
+ # API_JSON_CODER = JSON::Coder.new do |object|
889
+ # case object
890
+ # when Time
891
+ # object.iso8601(3)
892
+ # else
893
+ # object # Unknown type, will raise
894
+ # end
895
+ # end
896
+ # end
897
+ #
898
+ # puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
899
+ #
900
+ def initialize(options = nil, &as_json)
901
+ if options.nil?
902
+ options = { strict: true }
903
+ else
904
+ options = options.dup
905
+ options[:strict] = true
906
+ end
907
+ options[:as_json] = as_json if as_json
908
+ options[:create_additions] = false unless options.key?(:create_additions)
909
+
910
+ @state = State.new(options).freeze
911
+ @parser_config = Ext::Parser::Config.new(options)
912
+ end
913
+
914
+ # call-seq:
915
+ # dump(object) -> String
916
+ # dump(object, io) -> io
917
+ #
918
+ # Serialize the given object into a \JSON document.
919
+ def dump(object, io = nil)
920
+ @state.generate_new(object, io)
921
+ end
922
+ alias_method :generate, :dump
923
+
924
+ # call-seq:
925
+ # load(string) -> Object
926
+ #
927
+ # Parse the given \JSON document and return an equivalent Ruby object.
928
+ def load(source)
929
+ @parser_config.parse(source)
930
+ end
931
+ alias_method :parse, :load
932
+
933
+ # call-seq:
934
+ # load(path) -> Object
935
+ #
936
+ # Parse the given \JSON document and return an equivalent Ruby object.
937
+ def load_file(path)
938
+ load(File.read(path, encoding: Encoding::UTF_8))
939
+ end
940
+ end
844
941
  end
845
942
 
846
943
  module ::Kernel
@@ -47,17 +47,6 @@ module JSON
47
47
 
48
48
  alias_method :merge, :configure
49
49
 
50
- # call-seq:
51
- # generate(obj) -> String
52
- # generate(obj, anIO) -> anIO
53
- #
54
- # Generates a valid JSON document from object +obj+ and returns the
55
- # result. If no valid JSON document can be created this method raises a
56
- # GeneratorError exception.
57
- def generate(obj, io = nil)
58
- _generate(obj, io)
59
- end
60
-
61
50
  # call-seq: to_h
62
51
  #
63
52
  # Returns the configuration instance variables as a hash, that can be
@@ -69,6 +58,7 @@ module JSON
69
58
  space_before: space_before,
70
59
  object_nl: object_nl,
71
60
  array_nl: array_nl,
61
+ as_json: as_json,
72
62
  allow_nan: allow_nan?,
73
63
  ascii_only: ascii_only?,
74
64
  max_nesting: max_nesting,
data/lib/json/ext.rb CHANGED
@@ -6,15 +6,37 @@ module JSON
6
6
  # This module holds all the modules/classes that implement JSON's
7
7
  # functionality as C extensions.
8
8
  module Ext
9
+ class Parser
10
+ class << self
11
+ def parse(...)
12
+ new(...).parse
13
+ end
14
+ alias_method :parse, :parse # Allow redefinition by extensions
15
+ end
16
+
17
+ def initialize(source, opts = nil)
18
+ @source = source
19
+ @config = Config.new(opts)
20
+ end
21
+
22
+ def source
23
+ @source.dup
24
+ end
25
+
26
+ def parse
27
+ @config.parse(@source)
28
+ end
29
+ end
30
+
31
+ require 'json/ext/parser'
32
+ Ext::Parser::Config = Ext::ParserConfig
33
+ JSON.parser = Ext::Parser
34
+
9
35
  if RUBY_ENGINE == 'truffleruby'
10
- require 'json/ext/parser'
11
36
  require 'json/truffle_ruby/generator'
12
- JSON.parser = Parser
13
37
  JSON.generator = ::JSON::TruffleRuby::Generator
14
38
  else
15
- require 'json/ext/parser'
16
39
  require 'json/ext/generator'
17
- JSON.parser = Parser
18
40
  JSON.generator = Generator
19
41
  end
20
42
  end
@@ -39,30 +39,33 @@ module JSON
39
39
  '\\' => '\\\\',
40
40
  }.freeze # :nodoc:
41
41
 
42
- ESCAPE_PATTERN = /[\/"\\\x0-\x1f]/n # :nodoc:
43
-
44
42
  SCRIPT_SAFE_MAP = MAP.merge(
45
43
  '/' => '\\/',
46
- "\u2028".b => '\u2028',
47
- "\u2029".b => '\u2029',
44
+ "\u2028" => '\u2028',
45
+ "\u2029" => '\u2029',
48
46
  ).freeze
49
47
 
50
- SCRIPT_SAFE_ESCAPE_PATTERN = Regexp.union(ESCAPE_PATTERN, "\u2028".b, "\u2029".b)
48
+ SCRIPT_SAFE_ESCAPE_PATTERN = /[\/"\\\x0-\x1f\u2028-\u2029]/
51
49
 
52
50
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
53
51
  # UTF16 big endian characters as \u????, and return it.
54
- def utf8_to_json(string, script_safe = false) # :nodoc:
55
- string = string.b
52
+ def self.utf8_to_json(string, script_safe = false) # :nodoc:
56
53
  if script_safe
57
- string.gsub!(SCRIPT_SAFE_ESCAPE_PATTERN) { SCRIPT_SAFE_MAP[$&] || $& }
54
+ if SCRIPT_SAFE_ESCAPE_PATTERN.match?(string)
55
+ string.gsub(SCRIPT_SAFE_ESCAPE_PATTERN, SCRIPT_SAFE_MAP)
56
+ else
57
+ string
58
+ end
58
59
  else
59
- string.gsub!(ESCAPE_PATTERN) { MAP[$&] || $& }
60
+ if /["\\\x0-\x1f]/.match?(string)
61
+ string.gsub(/["\\\x0-\x1f]/, MAP)
62
+ else
63
+ string
64
+ end
60
65
  end
61
- string.force_encoding(::Encoding::UTF_8)
62
- string
63
66
  end
64
67
 
65
- def utf8_to_json_ascii(original_string, script_safe = false) # :nodoc:
68
+ def self.utf8_to_json_ascii(original_string, script_safe = false) # :nodoc:
66
69
  string = original_string.b
67
70
  map = script_safe ? SCRIPT_SAFE_MAP : MAP
68
71
  string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
@@ -86,24 +89,17 @@ module JSON
86
89
  raise GeneratorError.new(e.message, original_string)
87
90
  end
88
91
 
89
- def valid_utf8?(string)
92
+ def self.valid_utf8?(string)
90
93
  encoding = string.encoding
91
94
  (encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
92
95
  string.valid_encoding?
93
96
  end
94
- module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
95
97
 
96
98
  # This class is used to create State instances, that are use to hold data
97
99
  # while generating a JSON text from a Ruby data structure.
98
100
  class State
99
101
  def self.generate(obj, opts = nil, io = nil)
100
- string = new(opts).generate(obj)
101
- if io
102
- io.write(string)
103
- io
104
- else
105
- string
106
- end
102
+ new(opts).generate(obj, io)
107
103
  end
108
104
 
109
105
  # Creates a State object from _opts_, which ought to be Hash to create
@@ -111,16 +107,17 @@ module JSON
111
107
  # an unconfigured instance. If _opts_ is a State object, it is just
112
108
  # returned.
113
109
  def self.from_state(opts)
114
- case
115
- when self === opts
116
- opts
117
- when opts.respond_to?(:to_hash)
118
- new(opts.to_hash)
119
- when opts.respond_to?(:to_h)
120
- new(opts.to_h)
121
- else
122
- SAFE_STATE_PROTOTYPE.dup
110
+ if opts
111
+ case
112
+ when self === opts
113
+ return opts
114
+ when opts.respond_to?(:to_hash)
115
+ return new(opts.to_hash)
116
+ when opts.respond_to?(:to_h)
117
+ return new(opts.to_h)
118
+ end
123
119
  end
120
+ SAFE_STATE_PROTOTYPE.dup
124
121
  end
125
122
 
126
123
  # Instantiates a new State object, configured by _opts_.
@@ -148,6 +145,7 @@ module JSON
148
145
  @array_nl = ''
149
146
  @allow_nan = false
150
147
  @ascii_only = false
148
+ @as_json = false
151
149
  @depth = 0
152
150
  @buffer_initial_length = 1024
153
151
  @script_safe = false
@@ -173,6 +171,9 @@ module JSON
173
171
  # This string is put at the end of a line that holds a JSON array.
174
172
  attr_accessor :array_nl
175
173
 
174
+ # This proc converts unsupported types into native JSON types.
175
+ attr_accessor :as_json
176
+
176
177
  # This integer returns the maximum level of data structure nesting in
177
178
  # the generated JSON, max_nesting = 0 if no maximum is checked.
178
179
  attr_accessor :max_nesting
@@ -257,6 +258,7 @@ module JSON
257
258
  @object_nl = opts[:object_nl] || '' if opts.key?(:object_nl)
258
259
  @array_nl = opts[:array_nl] || '' if opts.key?(:array_nl)
259
260
  @allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
261
+ @as_json = opts[:as_json].to_proc if opts.key?(:as_json)
260
262
  @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
261
263
  @depth = opts[:depth] || 0
262
264
  @buffer_initial_length ||= opts[:buffer_initial_length]
@@ -299,9 +301,9 @@ module JSON
299
301
  # returns the result. If no valid JSON document can be
300
302
  # created this method raises a
301
303
  # GeneratorError exception.
302
- def generate(obj)
304
+ def generate(obj, anIO = nil)
303
305
  if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and
304
- !@ascii_only and !@script_safe and @max_nesting == 0 and !@strict
306
+ !@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj)
305
307
  result = generate_json(obj, ''.dup)
306
308
  else
307
309
  result = obj.to_json(self)
@@ -310,7 +312,16 @@ module JSON
310
312
  "source sequence #{result.inspect} is illegal/malformed utf-8",
311
313
  obj
312
314
  )
313
- result
315
+ if anIO
316
+ anIO.write(result)
317
+ anIO
318
+ else
319
+ result
320
+ end
321
+ end
322
+
323
+ def generate_new(obj, anIO = nil) # :nodoc:
324
+ dup.generate(obj, anIO)
314
325
  end
315
326
 
316
327
  # Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
@@ -353,6 +364,12 @@ module JSON
353
364
  end
354
365
  when Integer
355
366
  buf << obj.to_s
367
+ when Symbol
368
+ if @strict
369
+ fast_serialize_string(obj.name, buf)
370
+ else
371
+ buf << obj.to_json(self)
372
+ end
356
373
  else
357
374
  # Note: Float is handled this way since Float#to_s is slow anyway
358
375
  buf << obj.to_json(self)
@@ -371,8 +388,8 @@ module JSON
371
388
  end
372
389
  raise GeneratorError.new("source sequence is illegal/malformed utf-8", string) unless string.valid_encoding?
373
390
 
374
- if /["\\\x0-\x1f]/n.match?(string)
375
- buf << string.gsub(/["\\\x0-\x1f]/n, MAP)
391
+ if /["\\\x0-\x1f]/.match?(string)
392
+ buf << string.gsub(/["\\\x0-\x1f]/, MAP)
376
393
  else
377
394
  buf << string
378
395
  end
@@ -404,8 +421,20 @@ module JSON
404
421
  # it to a JSON string, and returns the result. This is a fallback, if no
405
422
  # special method #to_json was defined for some object.
406
423
  def to_json(state = nil, *)
407
- if state && State.from_state(state).strict?
408
- raise GeneratorError.new("#{self.class} not allowed in JSON", self)
424
+ state = State.from_state(state) if state
425
+ if state&.strict?
426
+ value = self
427
+ if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
428
+ if state.as_json
429
+ value = state.as_json.call(value)
430
+ unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value
431
+ raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
432
+ end
433
+ value.to_json(state)
434
+ else
435
+ raise GeneratorError.new("#{value.class} not allowed in JSON", value)
436
+ end
437
+ end
409
438
  else
410
439
  to_s.to_json
411
440
  end
@@ -455,8 +484,16 @@ module JSON
455
484
  end
456
485
 
457
486
  result = +"#{result}#{key_json}#{state.space_before}:#{state.space}"
458
- if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
459
- raise GeneratorError.new("#{value.class} not allowed in JSON", value)
487
+ if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
488
+ if state.as_json
489
+ value = state.as_json.call(value)
490
+ unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value
491
+ raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
492
+ end
493
+ result << value.to_json(state)
494
+ else
495
+ raise GeneratorError.new("#{value.class} not allowed in JSON", value)
496
+ end
460
497
  elsif value.respond_to?(:to_json)
461
498
  result << value.to_json(state)
462
499
  else
@@ -508,8 +545,16 @@ module JSON
508
545
  each { |value|
509
546
  result << delim unless first
510
547
  result << state.indent * depth if indent
511
- if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
512
- raise GeneratorError.new("#{value.class} not allowed in JSON", value)
548
+ if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value || Symbol == value)
549
+ if state.as_json
550
+ value = state.as_json.call(value)
551
+ unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value || Symbol === value
552
+ raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
553
+ end
554
+ result << value.to_json(state)
555
+ else
556
+ raise GeneratorError.new("#{value.class} not allowed in JSON", value)
557
+ end
513
558
  elsif value.respond_to?(:to_json)
514
559
  result << value.to_json(state)
515
560
  else
@@ -531,18 +576,23 @@ module JSON
531
576
 
532
577
  module Float
533
578
  # Returns a JSON string representation for this Float number.
534
- def to_json(state = nil, *)
579
+ def to_json(state = nil, *args)
535
580
  state = State.from_state(state)
536
- case
537
- when infinite?
538
- if state.allow_nan?
539
- to_s
540
- else
541
- raise GeneratorError.new("#{self} not allowed in JSON", self)
542
- end
543
- when nan?
581
+ if infinite? || nan?
544
582
  if state.allow_nan?
545
583
  to_s
584
+ elsif state.strict? && state.as_json
585
+ casted_value = state.as_json.call(self)
586
+
587
+ if casted_value.equal?(self)
588
+ raise GeneratorError.new("#{self} not allowed in JSON", self)
589
+ end
590
+
591
+ state.check_max_nesting
592
+ state.depth += 1
593
+ result = casted_value.to_json(state, *args)
594
+ state.depth -= 1
595
+ result
546
596
  else
547
597
  raise GeneratorError.new("#{self} not allowed in JSON", self)
548
598
  end
@@ -552,6 +602,17 @@ module JSON
552
602
  end
553
603
  end
554
604
 
605
+ module Symbol
606
+ def to_json(state = nil, *args)
607
+ state = State.from_state(state)
608
+ if state.strict?
609
+ name.to_json(state, *args)
610
+ else
611
+ super
612
+ end
613
+ end
614
+ end
615
+
555
616
  module String
556
617
  # This string should be encoded with UTF-8 A call to this method
557
618
  # returns a JSON string encoded with UTF16 big endian characters as
data/lib/json/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSON
4
- VERSION = '2.9.1'
4
+ VERSION = '2.10.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.1
4
+ version: 2.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-12-18 00:00:00.000000000 Z
10
+ date: 2025-02-10 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: This is a JSON implementation as a Ruby extension in C.
14
13
  email: flori@ping.de
@@ -29,7 +28,6 @@ files:
29
28
  - ext/json/ext/generator/generator.c
30
29
  - ext/json/ext/parser/extconf.rb
31
30
  - ext/json/ext/parser/parser.c
32
- - ext/json/ext/parser/parser.rl
33
31
  - json.gemspec
34
32
  - lib/json.rb
35
33
  - lib/json/add/bigdecimal.rb
@@ -52,17 +50,15 @@ files:
52
50
  - lib/json/generic_object.rb
53
51
  - lib/json/truffle_ruby/generator.rb
54
52
  - lib/json/version.rb
55
- homepage: https://ruby.github.io/json
53
+ homepage: https://github.com/ruby/json
56
54
  licenses:
57
55
  - Ruby
58
56
  metadata:
59
57
  bug_tracker_uri: https://github.com/ruby/json/issues
60
58
  changelog_uri: https://github.com/ruby/json/blob/master/CHANGES.md
61
- documentation_uri: https://ruby.github.io/json/doc/index.html
62
- homepage_uri: https://ruby.github.io/json
59
+ documentation_uri: https://docs.ruby-lang.org/en/master/JSON.html
60
+ homepage_uri: https://github.com/ruby/json
63
61
  source_code_uri: https://github.com/ruby/json
64
- wiki_uri: https://github.com/ruby/json/wiki
65
- post_install_message:
66
62
  rdoc_options:
67
63
  - "--title"
68
64
  - JSON implementation for Ruby
@@ -81,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
77
  - !ruby/object:Gem::Version
82
78
  version: '0'
83
79
  requirements: []
84
- rubygems_version: 3.5.11
85
- signing_key:
80
+ rubygems_version: 3.6.2
86
81
  specification_version: 4
87
82
  summary: JSON Implementation for Ruby
88
83
  test_files: []