json 2.21.2 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/json/common.rb CHANGED
@@ -3,25 +3,12 @@
3
3
  require 'json/version'
4
4
 
5
5
  module JSON
6
- autoload :GenericObject, 'json/generic_object'
7
-
8
6
  module ParserOptions # :nodoc:
9
7
  class << self
10
- def prepare(opts)
11
- if opts[:object_class] || opts[:array_class]
12
- opts = opts.dup
13
- on_load = opts[:on_load]
14
-
15
- on_load = object_class_proc(opts[:object_class], on_load) if opts[:object_class]
16
- on_load = array_class_proc(opts[:array_class], on_load) if opts[:array_class]
17
- opts[:on_load] = on_load
18
- end
19
-
20
- if opts.fetch(:create_additions, false) != false
21
- opts = create_additions_proc(opts)
22
- end
23
-
24
- opts
8
+ def on_load(on_load, object_class, array_class)
9
+ on_load = object_class_proc(object_class, on_load) if object_class
10
+ on_load = array_class_proc(array_class, on_load) if array_class
11
+ on_load
25
12
  end
26
13
 
27
14
  private
@@ -47,77 +34,12 @@ module JSON
47
34
  on_load.nil? ? obj : on_load.call(obj)
48
35
  end
49
36
  end
50
-
51
- # TODO: extract :create_additions support to another gem for version 3.0
52
- def create_additions_proc(opts)
53
- if opts[:symbolize_names]
54
- raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
55
- end
56
-
57
- opts = opts.dup
58
- create_additions = opts.fetch(:create_additions, false)
59
- on_load = opts[:on_load]
60
- object_class = opts[:object_class] || Hash
61
-
62
- opts[:on_load] = ->(object) do
63
- case object
64
- when String
65
- opts[:match_string]&.each do |pattern, klass|
66
- if match = pattern.match(object)
67
- create_additions_warning if create_additions.nil?
68
- object = klass.json_create(object)
69
- break
70
- end
71
- end
72
- when object_class
73
- if opts[:create_additions] != false
74
- if class_path = object[JSON.create_id]
75
- klass = begin
76
- Object.const_get(class_path)
77
- rescue NameError => e
78
- raise ArgumentError, "can't get const #{class_path}: #{e}"
79
- end
80
-
81
- if klass.respond_to?(:json_creatable?) ? klass.json_creatable? : klass.respond_to?(:json_create)
82
- create_additions_warning if create_additions.nil?
83
- object = klass.json_create(object)
84
- end
85
- end
86
- end
87
- end
88
-
89
- on_load.nil? ? object : on_load.call(object)
90
- end
91
-
92
- opts
93
- end
94
-
95
- def create_additions_warning
96
- JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
97
- "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
98
- "pass `create_additions: true`"
99
- end
100
37
  end
101
38
  end
102
39
 
103
- class << self
104
- def deprecation_warning(message, uplevel = 3) # :nodoc:
105
- gem_root = File.expand_path("..", __dir__) + "/"
106
- caller_locations(uplevel, 10).each do |frame|
107
- if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
108
- uplevel += 1
109
- else
110
- break
111
- end
112
- end
113
-
114
- if RUBY_VERSION >= "3.0"
115
- warn(message, uplevel: uplevel, category: :deprecated)
116
- else
117
- warn(message, uplevel: uplevel)
118
- end
119
- end
40
+ private_constant :ParserOptions
120
41
 
42
+ class << self
121
43
  # :call-seq:
122
44
  # JSON[object] -> new_array or new_string
123
45
  #
@@ -130,12 +52,14 @@ module JSON
130
52
  # ruby = [0, 1, nil]
131
53
  # JSON[ruby] # => '[0,1,null]'
132
54
  def [](object, opts = nil)
55
+ opts ||= {}.freeze
56
+
133
57
  if object.is_a?(String)
134
- return JSON.parse(object, opts)
58
+ return JSON.parse(object, **opts)
135
59
  elsif object.respond_to?(:to_str)
136
60
  str = object.to_str
137
61
  if str.is_a?(String)
138
- return JSON.parse(str, opts)
62
+ return JSON.parse(str, **opts)
139
63
  end
140
64
  end
141
65
 
@@ -193,57 +117,18 @@ module JSON
193
117
  private
194
118
 
195
119
  # Called from the extension when a hash has both string and symbol keys
196
- def on_mixed_keys_hash(hash, do_raise)
120
+ def on_mixed_keys_hash(hash)
197
121
  set = {}
198
122
  hash.each_key do |key|
199
123
  key_str = key.to_s
200
124
 
201
125
  if set[key_str]
202
- message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
203
- if do_raise
204
- raise GeneratorError, message
205
- else
206
- deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
207
- end
126
+ raise GeneratorError, "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
208
127
  else
209
128
  set[key_str] = true
210
129
  end
211
130
  end
212
131
  end
213
-
214
- def deprecated_singleton_attr_accessor(*attrs)
215
- args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
216
- attrs.each do |attr|
217
- singleton_class.class_eval <<~RUBY
218
- def #{attr}
219
- warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
220
- @#{attr}
221
- end
222
-
223
- def #{attr}=(val)
224
- warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
225
- @#{attr} = val
226
- end
227
-
228
- def _#{attr}
229
- @#{attr}
230
- end
231
- RUBY
232
- end
233
- end
234
- end
235
-
236
- # Sets create identifier, which is used to decide if the _json_create_
237
- # hook of a class should be called; initial value is +json_class+:
238
- # JSON.create_id # => 'json_class'
239
- def self.create_id=(new_value)
240
- Thread.current[:"JSON.create_id"] = new_value.dup.freeze
241
- end
242
-
243
- # Returns the current create identifier.
244
- # See also JSON.create_id=.
245
- def self.create_id
246
- Thread.current[:"JSON.create_id"] || 'json_class'
247
132
  end
248
133
 
249
134
  NaN = Float::NAN
@@ -257,7 +142,56 @@ module JSON
257
142
 
258
143
  # This exception is raised if a parser error occurs.
259
144
  class ParserError < JSONError
260
- attr_reader :line, :column
145
+ # Line number where the parser encountered an error.
146
+ # Is <tt>nil</tt> when raised by JSON::ResumableParser.
147
+ attr_reader :line
148
+
149
+ # Column number where the parser encountered an error.
150
+ # Is <tt>nil</tt> when raised by JSON::ResumableParser.
151
+ attr_reader :column
152
+
153
+ # Returns a best effort JSONPath string representing where in the document
154
+ # the parser encountered an error:
155
+ #
156
+ # begin
157
+ # JSON.parse('{"articles": [ { "title": invalid } ]}')
158
+ # rescue JSON::ParserError => error
159
+ # error.json_path # => "$.articles[0].title"
160
+ # end
161
+ def json_path
162
+ return @json_path if String === @json_path
163
+
164
+ if Array === @json_path
165
+ path = build_json_path(@json_path)
166
+ @json_path = path unless frozen?
167
+ return path
168
+ end
169
+ end
170
+
171
+ private
172
+
173
+ def build_json_path(segments)
174
+ error = false
175
+ path = segments.filter_map do |segment|
176
+ next if error
177
+
178
+ case segment
179
+ when Integer
180
+ "[#{segment}]"
181
+ when String, Symbol
182
+ if segment.match?(/\A[a-zA-Z\$\_][a-zA-Z\$\_0-9]*\z/)
183
+ ".#{segment}"
184
+ else
185
+ segment = segment.to_s.gsub(/["\\]/, { '"' => '\\"', '\\' => '\\\\' })
186
+ %{["#{segment}"]}
187
+ end
188
+ else
189
+ error = true
190
+ nil
191
+ end
192
+ end.join
193
+ "$#{path}".freeze
194
+ end
261
195
  end
262
196
 
263
197
  # This exception is raised if the nesting of parsed data structures is too
@@ -356,19 +290,17 @@ module JSON
356
290
  # ---
357
291
  #
358
292
  # Raises an exception if +source+ is not valid JSON:
359
- # # Raises JSON::ParserError (783: unexpected token at ''):
360
- # JSON.parse('')
293
+ # # Raises JSON::ParserError unexpected character: 'invalid' at line 1 column 1 :
294
+ # JSON.parse('invalid')
361
295
  #
362
- def parse(source, opts = nil)
363
- opts = ParserOptions.prepare(opts) unless opts.nil?
364
- Parser.parse(source, opts)
365
- end
296
+ def parse(source, on_load: nil, object_class: nil, array_class: nil, **options)
297
+ if object_class || array_class
298
+ on_load = ParserOptions.on_load(on_load, object_class, array_class)
299
+ end
366
300
 
367
- PARSE_L_OPTIONS = {
368
- max_nesting: false,
369
- allow_nan: true,
370
- }.freeze
371
- private_constant :PARSE_L_OPTIONS
301
+ options[:on_load] = on_load if on_load
302
+ Parser.parse(source, options)
303
+ end
372
304
 
373
305
  # :call-seq:
374
306
  # JSON.parse!(source, opts) -> object
@@ -381,34 +313,30 @@ module JSON
381
313
  # - Option +max_nesting+, if not provided, defaults to +false+,
382
314
  # which disables checking for nesting depth.
383
315
  # - Option +allow_nan+, if not provided, defaults to +true+.
384
- def parse!(source, opts = nil)
385
- if opts.nil?
386
- parse(source, PARSE_L_OPTIONS)
387
- else
388
- parse(source, PARSE_L_OPTIONS.merge(opts))
389
- end
316
+ def parse!(source, **options)
317
+ parse(source, max_nesting: false, allow_nan: true, **options)
390
318
  end
391
319
 
392
320
  # :call-seq:
393
- # JSON.load_file(path, opts={}) -> object
321
+ # JSON.load_file(path, **) -> object
394
322
  #
395
323
  # Calls:
396
- # parse(File.read(path), opts)
324
+ # parse(File.read(path), **)
397
325
  #
398
326
  # See method #parse.
399
- def load_file(filespec, opts = nil)
400
- parse(File.read(filespec, encoding: Encoding::UTF_8), opts)
327
+ def load_file(filespec, ...)
328
+ parse(File.read(filespec, encoding: Encoding::UTF_8), ...)
401
329
  end
402
330
 
403
331
  # :call-seq:
404
- # JSON.load_file!(path, opts = {})
332
+ # JSON.load_file!(path, **)
405
333
  #
406
334
  # Calls:
407
- # JSON.parse!(File.read(path, opts))
335
+ # JSON.parse!(File.read(path), **)
408
336
  #
409
337
  # See method #parse!
410
- def load_file!(filespec, opts = nil)
411
- parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
338
+ def load_file!(filespec, ...)
339
+ parse!(File.read(filespec, encoding: Encoding::UTF_8), ...)
412
340
  end
413
341
 
414
342
  # :call-seq:
@@ -451,32 +379,10 @@ module JSON
451
379
  if State === opts
452
380
  opts.generate(obj)
453
381
  else
454
- State.generate(obj, opts, nil)
382
+ State.generate(obj, opts.frozen? ? opts : opts.dup, nil)
455
383
  end
456
384
  end
457
385
 
458
- # :call-seq:
459
- # JSON.fast_generate(obj, opts) -> new_string
460
- #
461
- # Arguments +obj+ and +opts+ here are the same as
462
- # arguments +obj+ and +opts+ in JSON.generate.
463
- #
464
- # By default, generates \JSON data without checking
465
- # for circular references in +obj+ (option +max_nesting+ set to +false+, disabled).
466
- #
467
- # Raises an exception if +obj+ contains circular references:
468
- # a = []; b = []; a.push(b); b.push(a)
469
- # # Raises SystemStackError (stack level too deep):
470
- # JSON.fast_generate(a)
471
- def fast_generate(obj, opts = nil)
472
- if RUBY_VERSION >= "3.0"
473
- warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
474
- else
475
- warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
476
- end
477
- generate(obj, opts)
478
- end
479
-
480
386
  PRETTY_GENERATE_OPTIONS = {
481
387
  indent: ' ',
482
388
  space: ' ',
@@ -530,43 +436,20 @@ module JSON
530
436
  raise TypeError, "can't convert #{opts.class} into Hash"
531
437
  end
532
438
  end
439
+
533
440
  options = options.merge(opts)
534
441
  end
535
442
 
536
443
  State.generate(obj, options, nil)
537
444
  end
538
445
 
539
- # Sets or returns default options for the JSON.unsafe_load method.
540
- # Initially:
541
- # opts = JSON.load_default_options
542
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
543
- deprecated_singleton_attr_accessor :unsafe_load_default_options
544
-
545
- @unsafe_load_default_options = {
546
- :max_nesting => false,
547
- :allow_nan => true,
548
- :allow_blank => true,
549
- :create_additions => true,
550
- }
551
-
552
- # Sets or returns default options for the JSON.load method.
553
- # Initially:
554
- # opts = JSON.load_default_options
555
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
556
- deprecated_singleton_attr_accessor :load_default_options
557
-
558
- @load_default_options = {
559
- :allow_nan => true,
560
- :allow_blank => true,
561
- :create_additions => nil,
562
- }
563
446
  # :call-seq:
564
447
  # JSON.unsafe_load(source, options = {}) -> object
565
448
  # JSON.unsafe_load(source, proc = nil, options = {}) -> object
566
449
  #
567
450
  # Returns the Ruby objects created by parsing the given +source+.
568
451
  #
569
- # BEWARE: This method is meant to serialise data from trusted user input,
452
+ # BEWARE: This method is meant to deserialise data from trusted user input,
570
453
  # like from your own database server or clients under your control, it could
571
454
  # be dangerous to allow untrusted users to pass JSON sources into it.
572
455
  #
@@ -586,7 +469,6 @@ module JSON
586
469
  # See details below.
587
470
  # - Argument +opts+, if given, contains a \Hash of options for the parsing.
588
471
  # See {Parsing Options}[#module-JSON-label-Parsing+Options].
589
- # The default options can be changed via method JSON.unsafe_load_default_options=.
590
472
  #
591
473
  # ---
592
474
  #
@@ -691,38 +573,8 @@ module JSON
691
573
  # #<Admin:0x00000000064c41f8
692
574
  # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
693
575
  #
694
- def unsafe_load(source, proc = nil, options = nil)
695
- opts = if options.nil?
696
- if proc && proc.is_a?(Hash)
697
- options, proc = proc, nil
698
- options
699
- else
700
- _unsafe_load_default_options
701
- end
702
- else
703
- _unsafe_load_default_options.merge(options)
704
- end
705
-
706
- unless source.is_a?(String)
707
- if source.respond_to? :to_str
708
- source = source.to_str
709
- elsif source.respond_to? :to_io
710
- source = source.to_io.read
711
- elsif source.respond_to?(:read)
712
- source = source.read
713
- end
714
- end
715
-
716
- if opts[:allow_blank] && (source.nil? || source.empty?)
717
- source = 'null'
718
- end
719
-
720
- if proc
721
- opts = opts.dup
722
- opts[:on_load] = proc.to_proc
723
- end
724
-
725
- parse(source, opts)
576
+ def unsafe_load(source, proc = nil, **options)
577
+ load(source, proc, max_nesting: false, **options)
726
578
  end
727
579
 
728
580
  # :call-seq:
@@ -731,16 +583,6 @@ module JSON
731
583
  #
732
584
  # Returns the Ruby objects created by parsing the given +source+.
733
585
  #
734
- # BEWARE: This method is meant to serialise data from trusted user input,
735
- # like from your own database server or clients under your control, it could
736
- # be dangerous to allow untrusted users to pass JSON sources into it.
737
- # If you must use it, use JSON.unsafe_load instead to make it clear.
738
- #
739
- # Since JSON version 2.8.0, `load` emits a deprecation warning when a
740
- # non native type is deserialized, without `create_additions` being explicitly
741
- # enabled, and in JSON version 3.0, `load` will have `create_additions` disabled
742
- # by default.
743
- #
744
586
  # - Argument +source+ must be, or be convertible to, a \String:
745
587
  # - If +source+ responds to instance method +to_str+,
746
588
  # <tt>source.to_str</tt> becomes the source.
@@ -757,7 +599,6 @@ module JSON
757
599
  # See details below.
758
600
  # - Argument +opts+, if given, contains a \Hash of options for the parsing.
759
601
  # See {Parsing Options}[#module-JSON-label-Parsing+Options].
760
- # The default options can be changed via method JSON.load_default_options=.
761
602
  #
762
603
  # ---
763
604
  #
@@ -862,23 +703,7 @@ module JSON
862
703
  # #<Admin:0x00000000064c41f8
863
704
  # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
864
705
  #
865
- def load(source, proc = nil, options = nil)
866
- if proc && options.nil? && proc.is_a?(Hash)
867
- options = proc
868
- proc = nil
869
- end
870
-
871
- opts = if options.nil?
872
- if proc && proc.is_a?(Hash)
873
- options, proc = proc, nil
874
- options
875
- else
876
- _load_default_options
877
- end
878
- else
879
- _load_default_options.merge(options)
880
- end
881
-
706
+ def load(source, proc = nil, allow_blank: true, **options)
882
707
  unless source.is_a?(String)
883
708
  if source.respond_to? :to_str
884
709
  source = source.to_str
@@ -889,40 +714,26 @@ module JSON
889
714
  end
890
715
  end
891
716
 
892
- if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
717
+ if allow_blank && (source.nil? || (String === source && source.empty?))
893
718
  source = 'null'
894
719
  end
895
720
 
896
721
  if proc
897
- opts = opts.dup
898
- opts[:on_load] = proc.to_proc
722
+ parse(source, allow_nan: true, on_load: proc.to_proc, **options)
723
+ else
724
+ parse(source, allow_nan: true, **options)
899
725
  end
900
-
901
- parse(source, opts)
902
726
  end
903
727
 
904
- # Sets or returns the default options for the JSON.dump method.
905
- # Initially:
906
- # opts = JSON.dump_default_options
907
- # opts # => {:max_nesting=>false, :allow_nan=>true}
908
- deprecated_singleton_attr_accessor :dump_default_options
909
- @dump_default_options = {
910
- :max_nesting => false,
911
- :allow_nan => true,
912
- }
913
-
914
728
  # :call-seq:
915
- # JSON.dump(obj, io = nil, limit = nil)
729
+ # JSON.dump(obj, io = nil, _deprecated_limit = nil, options = nil)
916
730
  #
917
731
  # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result.
918
732
  #
919
- # The default options can be changed via method JSON.dump_default_options.
920
- #
921
733
  # - Argument +io+, if given, should respond to method +write+;
922
734
  # the \JSON \String is written to +io+, and +io+ is returned.
923
735
  # If +io+ is not given, the \JSON \String is returned.
924
- # - Argument +limit+, if given, is passed to JSON.generate as option +max_nesting+.
925
- #
736
+ # - Argument +_deprecated_limit+ is deprecated, pass the +:max_nesting+ option instead.
926
737
  # ---
927
738
  #
928
739
  # When argument +io+ is not given, returns the \JSON \String generated from +obj+:
@@ -938,100 +749,36 @@ module JSON
938
749
  # puts File.read(path)
939
750
  # Output:
940
751
  # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
941
- def dump(obj, anIO = nil, limit = nil, kwargs = nil)
752
+ def dump(obj, anIO = nil, _deprecated_limit = nil, kwargs = nil)
942
753
  if kwargs.nil?
943
- if limit.nil?
754
+ if _deprecated_limit.nil?
944
755
  if anIO.is_a?(Hash)
945
756
  kwargs = anIO
946
757
  anIO = nil
947
758
  end
948
- elsif limit.is_a?(Hash)
949
- kwargs = limit
950
- limit = nil
759
+ elsif _deprecated_limit.is_a?(Hash)
760
+ kwargs = _deprecated_limit
761
+ _deprecated_limit = nil
951
762
  end
952
763
  end
953
764
 
954
765
  unless anIO.nil?
955
766
  if anIO.respond_to?(:to_io)
956
767
  anIO = anIO.to_io
957
- elsif limit.nil? && !anIO.respond_to?(:write)
958
- anIO, limit = nil, anIO
768
+ elsif _deprecated_limit.nil? && !anIO.respond_to?(:write)
769
+ anIO, _deprecated_limit = nil, anIO
959
770
  end
960
771
  end
961
772
 
962
- opts = JSON._dump_default_options
963
- opts = opts.merge(:max_nesting => limit) if limit
964
- opts = opts.merge(kwargs) if kwargs
773
+ opts = {
774
+ allow_nan: true,
775
+ }
776
+ opts[:max_nesting] = _deprecated_limit if _deprecated_limit
777
+ opts.merge!(kwargs) if kwargs
965
778
 
966
- begin
967
- State.generate(obj, opts, anIO)
968
- rescue JSON::NestingError
969
- raise ArgumentError, "exceed depth limit"
970
- end
779
+ State.generate(obj, opts, anIO)
971
780
  end
972
781
 
973
- # :stopdoc:
974
- # All these were meant to be deprecated circa 2009, but were just set as undocumented
975
- # so usage still exist in the wild.
976
- def unparse(...)
977
- if RUBY_VERSION >= "3.0"
978
- warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
979
- else
980
- warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
981
- end
982
- generate(...)
983
- end
984
- module_function :unparse
985
-
986
- def fast_unparse(...)
987
- if RUBY_VERSION >= "3.0"
988
- warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
989
- else
990
- warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
991
- end
992
- generate(...)
993
- end
994
- module_function :fast_unparse
995
-
996
- def pretty_unparse(...)
997
- if RUBY_VERSION >= "3.0"
998
- warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
999
- else
1000
- warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
1001
- end
1002
- pretty_generate(...)
1003
- end
1004
- module_function :fast_unparse
1005
-
1006
- def restore(...)
1007
- if RUBY_VERSION >= "3.0"
1008
- warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated
1009
- else
1010
- warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1
1011
- end
1012
- load(...)
1013
- end
1014
- module_function :restore
1015
-
1016
- class << self
1017
- private
1018
-
1019
- def const_missing(const_name)
1020
- case const_name
1021
- when :PRETTY_STATE_PROTOTYPE
1022
- if RUBY_VERSION >= "3.0"
1023
- warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
1024
- else
1025
- warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
1026
- end
1027
- state.new(PRETTY_GENERATE_OPTIONS)
1028
- else
1029
- super
1030
- end
1031
- end
1032
- end
1033
- # :startdoc:
1034
-
1035
782
  # JSON::Coder holds a parser and generator configuration.
1036
783
  #
1037
784
  # module MyApp
@@ -1043,6 +790,27 @@ module JSON
1043
790
  # MyApp::JSONC_CODER.load(document)
1044
791
  #
1045
792
  class Coder
793
+ PARSER_OPTIONS = %i(
794
+ max_nesting
795
+ allow_nan
796
+ allow_trailing_comma
797
+ allow_comments
798
+ allow_control_characters
799
+ allow_invalid_escape
800
+ symbolize_names
801
+ freeze
802
+ allow_duplicate_key
803
+ decimal_class
804
+ ).freeze
805
+ private_constant :PARSER_OPTIONS
806
+
807
+ EXCLUDED_GENERATOR_OPTIONS = (PARSER_OPTIONS - %i(
808
+ max_nesting
809
+ allow_nan
810
+ allow_duplicate_key
811
+ )).freeze
812
+ private_constant :EXCLUDED_GENERATOR_OPTIONS
813
+
1046
814
  # :call-seq:
1047
815
  # JSON.new(options = nil, &block)
1048
816
  #
@@ -1067,17 +835,20 @@ module JSON
1067
835
  #
1068
836
  # puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
1069
837
  #
1070
- def initialize(options = nil, &as_json)
1071
- if options.nil?
1072
- options = { strict: true }
1073
- else
1074
- options = options.dup
1075
- options[:strict] = true
838
+ def initialize(object_class: nil, array_class: nil, on_load: nil, **options, &as_json)
839
+ if object_class || array_class
840
+ on_load = ParserOptions.on_load(on_load, object_class, array_class)
1076
841
  end
1077
- options[:as_json] = as_json if as_json
842
+ parser_options = options.slice(*PARSER_OPTIONS)
843
+ parser_options[:on_load] = on_load if on_load
844
+ @parser_config = Ext::Parser::Config.new(parser_options).freeze
1078
845
 
1079
- @state = State.new(options).freeze
1080
- @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
846
+ generator_options = options.reject { |k, _| EXCLUDED_GENERATOR_OPTIONS.include?(k) }
847
+ @state = State.new(
848
+ **generator_options,
849
+ strict: true,
850
+ as_json: as_json,
851
+ ).freeze
1081
852
  end
1082
853
 
1083
854
  # call-seq:
@@ -1136,36 +907,6 @@ end
1136
907
  module ::Kernel
1137
908
  private
1138
909
 
1139
- # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
1140
- # one line.
1141
- def j(*objs)
1142
- if RUBY_VERSION >= "3.0"
1143
- warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
1144
- else
1145
- warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
1146
- end
1147
-
1148
- objs.each do |obj|
1149
- puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
1150
- end
1151
- nil
1152
- end
1153
-
1154
- # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
1155
- # indentation and over many lines.
1156
- def jj(*objs)
1157
- if RUBY_VERSION >= "3.0"
1158
- warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
1159
- else
1160
- warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
1161
- end
1162
-
1163
- objs.each do |obj|
1164
- puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
1165
- end
1166
- nil
1167
- end
1168
-
1169
910
  # If _object_ is string-like, parse the string and return the parsed result as
1170
911
  # a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
1171
912
  # structure object and return it.