json 2.9.1 → 2.18.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
@@ -5,10 +5,119 @@ require 'json/version'
5
5
  module JSON
6
6
  autoload :GenericObject, 'json/generic_object'
7
7
 
8
- NOT_SET = Object.new.freeze
9
- private_constant :NOT_SET
8
+ module ParserOptions # :nodoc:
9
+ 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
25
+ end
26
+
27
+ private
28
+
29
+ def object_class_proc(object_class, on_load)
30
+ ->(obj) do
31
+ if Hash === obj
32
+ object = object_class.new
33
+ obj.each { |k, v| object[k] = v }
34
+ obj = object
35
+ end
36
+ on_load.nil? ? obj : on_load.call(obj)
37
+ end
38
+ end
39
+
40
+ def array_class_proc(array_class, on_load)
41
+ ->(obj) do
42
+ if Array === obj
43
+ array = array_class.new
44
+ obj.each { |v| array << v }
45
+ obj = array
46
+ end
47
+ on_load.nil? ? obj : on_load.call(obj)
48
+ end
49
+ 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
+ end
101
+ end
10
102
 
11
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
120
+
12
121
  # :call-seq:
13
122
  # JSON[object] -> new_array or new_string
14
123
  #
@@ -20,7 +129,7 @@ module JSON
20
129
  # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
21
130
  # ruby = [0, 1, nil]
22
131
  # JSON[ruby] # => '[0,1,null]'
23
- def [](object, opts = {})
132
+ def [](object, opts = nil)
24
133
  if object.is_a?(String)
25
134
  return JSON.parse(object, opts)
26
135
  elsif object.respond_to?(:to_str)
@@ -43,16 +152,6 @@ module JSON
43
152
  const_set :Parser, parser
44
153
  end
45
154
 
46
- # Return the constant located at _path_. The format of _path_ has to be
47
- # either ::A::B::C or A::B::C. In any case, A has to be located at the top
48
- # level (absolute namespace path?). If there doesn't exist a constant at
49
- # the given path, an ArgumentError is raised.
50
- def deep_const_get(path) # :nodoc:
51
- Object.const_get(path)
52
- rescue NameError => e
53
- raise ArgumentError, "can't get const #{path}: #{e}"
54
- end
55
-
56
155
  # Set the module _generator_ to be used by JSON.
57
156
  def generator=(generator) # :nodoc:
58
157
  old, $VERBOSE = $VERBOSE, nil
@@ -69,38 +168,58 @@ module JSON
69
168
  end
70
169
  end
71
170
  self.state = generator::State
72
- const_set :State, self.state
73
- const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby
74
- const_set :FAST_STATE_PROTOTYPE, create_fast_state
75
- const_set :PRETTY_STATE_PROTOTYPE, create_pretty_state
171
+ const_set :State, state
76
172
  ensure
77
173
  $VERBOSE = old
78
174
  end
79
175
 
80
- def create_fast_state
81
- State.new(
82
- :indent => '',
83
- :space => '',
84
- :object_nl => "",
85
- :array_nl => "",
86
- :max_nesting => false
87
- )
88
- end
89
-
90
- def create_pretty_state
91
- State.new(
92
- :indent => ' ',
93
- :space => ' ',
94
- :object_nl => "\n",
95
- :array_nl => "\n"
96
- )
97
- end
98
-
99
176
  # Returns the JSON generator module that is used by JSON.
100
177
  attr_reader :generator
101
178
 
102
179
  # Sets or Returns the JSON generator state class that is used by JSON.
103
180
  attr_accessor :state
181
+
182
+ private
183
+
184
+ # Called from the extension when a hash has both string and symbol keys
185
+ def on_mixed_keys_hash(hash, do_raise)
186
+ set = {}
187
+ hash.each_key do |key|
188
+ key_str = key.to_s
189
+
190
+ if set[key_str]
191
+ message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
192
+ if do_raise
193
+ raise GeneratorError, message
194
+ else
195
+ deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
196
+ end
197
+ else
198
+ set[key_str] = true
199
+ end
200
+ end
201
+ end
202
+
203
+ def deprecated_singleton_attr_accessor(*attrs)
204
+ args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
205
+ attrs.each do |attr|
206
+ singleton_class.class_eval <<~RUBY
207
+ def #{attr}
208
+ warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
209
+ @#{attr}
210
+ end
211
+
212
+ def #{attr}=(val)
213
+ warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
214
+ @#{attr} = val
215
+ end
216
+
217
+ def _#{attr}
218
+ @#{attr}
219
+ end
220
+ RUBY
221
+ end
222
+ end
104
223
  end
105
224
 
106
225
  # Sets create identifier, which is used to decide if the _json_create_
@@ -116,32 +235,24 @@ module JSON
116
235
  Thread.current[:"JSON.create_id"] || 'json_class'
117
236
  end
118
237
 
119
- NaN = 0.0/0
238
+ NaN = Float::NAN
120
239
 
121
- Infinity = 1.0/0
240
+ Infinity = Float::INFINITY
122
241
 
123
242
  MinusInfinity = -Infinity
124
243
 
125
244
  # The base exception for JSON errors.
126
- class JSONError < StandardError
127
- def self.wrap(exception)
128
- obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}")
129
- obj.set_backtrace exception.backtrace
130
- obj
131
- end
132
- end
245
+ class JSONError < StandardError; end
133
246
 
134
247
  # This exception is raised if a parser error occurs.
135
- class ParserError < JSONError; end
248
+ class ParserError < JSONError
249
+ attr_reader :line, :column
250
+ end
136
251
 
137
252
  # This exception is raised if the nesting of parsed data structures is too
138
253
  # deep.
139
254
  class NestingError < ParserError; end
140
255
 
141
- # :stopdoc:
142
- class CircularDatastructure < NestingError; end
143
- # :startdoc:
144
-
145
256
  # This exception is raised if a generator or unparser error occurs.
146
257
  class GeneratorError < JSONError
147
258
  attr_reader :invalid_object
@@ -152,20 +263,40 @@ module JSON
152
263
  end
153
264
 
154
265
  def detailed_message(...)
266
+ # Exception#detailed_message doesn't exist until Ruby 3.2
267
+ super_message = defined?(super) ? super : message
268
+
155
269
  if @invalid_object.nil?
156
- super
270
+ super_message
157
271
  else
158
- "#{super}\nInvalid object: #{@invalid_object.inspect}"
272
+ "#{super_message}\nInvalid object: #{@invalid_object.inspect}"
159
273
  end
160
274
  end
161
275
  end
162
276
 
163
- # For backwards compatibility
164
- UnparserError = GeneratorError # :nodoc:
277
+ # Fragment of JSON document that is to be included as is:
278
+ # fragment = JSON::Fragment.new("[1, 2, 3]")
279
+ # JSON.generate({ count: 3, items: fragments })
280
+ #
281
+ # This allows to easily assemble multiple JSON fragments that have
282
+ # been persisted somewhere without having to parse them nor resorting
283
+ # to string interpolation.
284
+ #
285
+ # Note: no validation is performed on the provided string. It is the
286
+ # responsibility of the caller to ensure the string contains valid JSON.
287
+ Fragment = Struct.new(:json) do
288
+ def initialize(json)
289
+ unless string = String.try_convert(json)
290
+ raise TypeError, " no implicit conversion of #{json.class} into String"
291
+ end
292
+
293
+ super(string)
294
+ end
165
295
 
166
- # This exception is raised if the required unicode support is missing on the
167
- # system. Usually this means that the iconv library is not installed.
168
- class MissingUnicodeSupport < JSONError; end
296
+ def to_json(state = nil, *)
297
+ json
298
+ end
299
+ end
169
300
 
170
301
  module_function
171
302
 
@@ -218,9 +349,16 @@ module JSON
218
349
  # JSON.parse('')
219
350
  #
220
351
  def parse(source, opts = nil)
352
+ opts = ParserOptions.prepare(opts) unless opts.nil?
221
353
  Parser.parse(source, opts)
222
354
  end
223
355
 
356
+ PARSE_L_OPTIONS = {
357
+ max_nesting: false,
358
+ allow_nan: true,
359
+ }.freeze
360
+ private_constant :PARSE_L_OPTIONS
361
+
224
362
  # :call-seq:
225
363
  # JSON.parse!(source, opts) -> object
226
364
  #
@@ -232,12 +370,12 @@ module JSON
232
370
  # - Option +max_nesting+, if not provided, defaults to +false+,
233
371
  # which disables checking for nesting depth.
234
372
  # - Option +allow_nan+, if not provided, defaults to +true+.
235
- def parse!(source, opts = {})
236
- opts = {
237
- :max_nesting => false,
238
- :allow_nan => true
239
- }.merge(opts)
240
- Parser.new(source, **(opts||{})).parse
373
+ def parse!(source, opts = nil)
374
+ if opts.nil?
375
+ parse(source, PARSE_L_OPTIONS)
376
+ else
377
+ parse(source, PARSE_L_OPTIONS.merge(opts))
378
+ end
241
379
  end
242
380
 
243
381
  # :call-seq:
@@ -258,7 +396,7 @@ module JSON
258
396
  # JSON.parse!(File.read(path, opts))
259
397
  #
260
398
  # See method #parse!
261
- def load_file!(filespec, opts = {})
399
+ def load_file!(filespec, opts = nil)
262
400
  parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
263
401
  end
264
402
 
@@ -267,7 +405,7 @@ module JSON
267
405
  #
268
406
  # Returns a \String containing the generated \JSON data.
269
407
  #
270
- # See also JSON.fast_generate, JSON.pretty_generate.
408
+ # See also JSON.pretty_generate.
271
409
  #
272
410
  # Argument +obj+ is the Ruby object to be converted to \JSON.
273
411
  #
@@ -306,13 +444,6 @@ module JSON
306
444
  end
307
445
  end
308
446
 
309
- # :stopdoc:
310
- # I want to deprecate these later, so I'll first be silent about them, and
311
- # later delete them.
312
- alias unparse generate
313
- module_function :unparse
314
- # :startdoc:
315
-
316
447
  # :call-seq:
317
448
  # JSON.fast_generate(obj, opts) -> new_string
318
449
  #
@@ -327,19 +458,21 @@ module JSON
327
458
  # # Raises SystemStackError (stack level too deep):
328
459
  # JSON.fast_generate(a)
329
460
  def fast_generate(obj, opts = nil)
330
- if State === opts
331
- state = opts
461
+ if RUBY_VERSION >= "3.0"
462
+ warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
332
463
  else
333
- state = JSON.create_fast_state.configure(opts)
464
+ warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
334
465
  end
335
- state.generate(obj)
466
+ generate(obj, opts)
336
467
  end
337
468
 
338
- # :stopdoc:
339
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
340
- alias fast_unparse fast_generate
341
- module_function :fast_unparse
342
- # :startdoc:
469
+ PRETTY_GENERATE_OPTIONS = {
470
+ indent: ' ',
471
+ space: ' ',
472
+ object_nl: "\n",
473
+ array_nl: "\n",
474
+ }.freeze
475
+ private_constant :PRETTY_GENERATE_OPTIONS
343
476
 
344
477
  # :call-seq:
345
478
  # JSON.pretty_generate(obj, opts = nil) -> new_string
@@ -372,57 +505,52 @@ module JSON
372
505
  # }
373
506
  #
374
507
  def pretty_generate(obj, opts = nil)
375
- if State === opts
376
- state, opts = opts, nil
377
- else
378
- state = JSON.create_pretty_state
379
- end
508
+ return opts.generate(obj) if State === opts
509
+
510
+ options = PRETTY_GENERATE_OPTIONS
511
+
380
512
  if opts
381
- if opts.respond_to? :to_hash
382
- opts = opts.to_hash
383
- elsif opts.respond_to? :to_h
384
- opts = opts.to_h
385
- else
386
- raise TypeError, "can't convert #{opts.class} into Hash"
513
+ unless opts.is_a?(Hash)
514
+ if opts.respond_to? :to_hash
515
+ opts = opts.to_hash
516
+ elsif opts.respond_to? :to_h
517
+ opts = opts.to_h
518
+ else
519
+ raise TypeError, "can't convert #{opts.class} into Hash"
520
+ end
387
521
  end
388
- state.configure(opts)
522
+ options = options.merge(opts)
389
523
  end
390
- state.generate(obj)
524
+
525
+ State.generate(obj, options, nil)
391
526
  end
392
527
 
393
- # :stopdoc:
394
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
395
- alias pretty_unparse pretty_generate
396
- module_function :pretty_unparse
397
- # :startdoc:
528
+ # Sets or returns default options for the JSON.unsafe_load method.
529
+ # Initially:
530
+ # opts = JSON.load_default_options
531
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
532
+ deprecated_singleton_attr_accessor :unsafe_load_default_options
398
533
 
399
- class << self
400
- # Sets or returns default options for the JSON.unsafe_load method.
401
- # Initially:
402
- # opts = JSON.load_default_options
403
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
404
- attr_accessor :unsafe_load_default_options
405
- end
406
- self.unsafe_load_default_options = {
534
+ @unsafe_load_default_options = {
407
535
  :max_nesting => false,
408
536
  :allow_nan => true,
409
537
  :allow_blank => true,
410
538
  :create_additions => true,
411
539
  }
412
540
 
413
- class << self
414
- # Sets or returns default options for the JSON.load method.
415
- # Initially:
416
- # opts = JSON.load_default_options
417
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
418
- attr_accessor :load_default_options
419
- end
420
- self.load_default_options = {
541
+ # Sets or returns default options for the JSON.load method.
542
+ # Initially:
543
+ # opts = JSON.load_default_options
544
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
545
+ deprecated_singleton_attr_accessor :load_default_options
546
+
547
+ @load_default_options = {
421
548
  :allow_nan => true,
422
549
  :allow_blank => true,
423
550
  :create_additions => nil,
424
551
  }
425
552
  # :call-seq:
553
+ # JSON.unsafe_load(source, options = {}) -> object
426
554
  # JSON.unsafe_load(source, proc = nil, options = {}) -> object
427
555
  #
428
556
  # Returns the Ruby objects created by parsing the given +source+.
@@ -530,6 +658,7 @@ module JSON
530
658
  # when Array
531
659
  # obj.map! {|v| deserialize_obj v }
532
660
  # end
661
+ # obj
533
662
  # })
534
663
  # pp ruby
535
664
  # Output:
@@ -553,9 +682,14 @@ module JSON
553
682
  #
554
683
  def unsafe_load(source, proc = nil, options = nil)
555
684
  opts = if options.nil?
556
- unsafe_load_default_options
685
+ if proc && proc.is_a?(Hash)
686
+ options, proc = proc, nil
687
+ options
688
+ else
689
+ _unsafe_load_default_options
690
+ end
557
691
  else
558
- unsafe_load_default_options.merge(options)
692
+ _unsafe_load_default_options.merge(options)
559
693
  end
560
694
 
561
695
  unless source.is_a?(String)
@@ -571,12 +705,17 @@ module JSON
571
705
  if opts[:allow_blank] && (source.nil? || source.empty?)
572
706
  source = 'null'
573
707
  end
574
- result = parse(source, opts)
575
- recurse_proc(result, &proc) if proc
576
- result
708
+
709
+ if proc
710
+ opts = opts.dup
711
+ opts[:on_load] = proc.to_proc
712
+ end
713
+
714
+ parse(source, opts)
577
715
  end
578
716
 
579
717
  # :call-seq:
718
+ # JSON.load(source, options = {}) -> object
580
719
  # JSON.load(source, proc = nil, options = {}) -> object
581
720
  #
582
721
  # Returns the Ruby objects created by parsing the given +source+.
@@ -690,6 +829,7 @@ module JSON
690
829
  # when Array
691
830
  # obj.map! {|v| deserialize_obj v }
692
831
  # end
832
+ # obj
693
833
  # })
694
834
  # pp ruby
695
835
  # Output:
@@ -712,10 +852,20 @@ module JSON
712
852
  # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
713
853
  #
714
854
  def load(source, proc = nil, options = nil)
855
+ if proc && options.nil? && proc.is_a?(Hash)
856
+ options = proc
857
+ proc = nil
858
+ end
859
+
715
860
  opts = if options.nil?
716
- load_default_options
861
+ if proc && proc.is_a?(Hash)
862
+ options, proc = proc, nil
863
+ options
864
+ else
865
+ _load_default_options
866
+ end
717
867
  else
718
- load_default_options.merge(options)
868
+ _load_default_options.merge(options)
719
869
  end
720
870
 
721
871
  unless source.is_a?(String)
@@ -731,36 +881,21 @@ module JSON
731
881
  if opts[:allow_blank] && (source.nil? || source.empty?)
732
882
  source = 'null'
733
883
  end
734
- result = parse(source, opts)
735
- recurse_proc(result, &proc) if proc
736
- result
737
- end
738
884
 
739
- # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
740
- def recurse_proc(result, &proc) # :nodoc:
741
- case result
742
- when Array
743
- result.each { |x| recurse_proc x, &proc }
744
- proc.call result
745
- when Hash
746
- result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
747
- proc.call result
748
- else
749
- proc.call result
885
+ if proc
886
+ opts = opts.dup
887
+ opts[:on_load] = proc.to_proc
750
888
  end
751
- end
752
-
753
- alias restore load
754
- module_function :restore
755
889
 
756
- class << self
757
- # Sets or returns the default options for the JSON.dump method.
758
- # Initially:
759
- # opts = JSON.dump_default_options
760
- # opts # => {:max_nesting=>false, :allow_nan=>true}
761
- attr_accessor :dump_default_options
890
+ parse(source, opts)
762
891
  end
763
- self.dump_default_options = {
892
+
893
+ # Sets or returns the default options for the JSON.dump method.
894
+ # Initially:
895
+ # opts = JSON.dump_default_options
896
+ # opts # => {:max_nesting=>false, :allow_nan=>true}
897
+ deprecated_singleton_attr_accessor :dump_default_options
898
+ @dump_default_options = {
764
899
  :max_nesting => false,
765
900
  :allow_nan => true,
766
901
  }
@@ -813,33 +948,152 @@ module JSON
813
948
  end
814
949
  end
815
950
 
816
- opts = JSON.dump_default_options
951
+ opts = JSON._dump_default_options
817
952
  opts = opts.merge(:max_nesting => limit) if limit
818
- opts = merge_dump_options(opts, **kwargs) if kwargs
953
+ opts = opts.merge(kwargs) if kwargs
819
954
 
820
955
  begin
821
- if State === opts
822
- opts.generate(obj, anIO)
823
- else
824
- State.generate(obj, opts, anIO)
825
- end
956
+ State.generate(obj, opts, anIO)
826
957
  rescue JSON::NestingError
827
958
  raise ArgumentError, "exceed depth limit"
828
959
  end
829
960
  end
830
961
 
831
- # Encodes string using String.encode.
832
- def self.iconv(to, from, string)
833
- string.encode(to, from)
962
+ # :stopdoc:
963
+ # All these were meant to be deprecated circa 2009, but were just set as undocumented
964
+ # so usage still exist in the wild.
965
+ def unparse(...)
966
+ if RUBY_VERSION >= "3.0"
967
+ warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
968
+ else
969
+ warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
970
+ end
971
+ generate(...)
972
+ end
973
+ module_function :unparse
974
+
975
+ def fast_unparse(...)
976
+ if RUBY_VERSION >= "3.0"
977
+ warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
978
+ else
979
+ warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
980
+ end
981
+ generate(...)
982
+ end
983
+ module_function :fast_unparse
984
+
985
+ def pretty_unparse(...)
986
+ if RUBY_VERSION >= "3.0"
987
+ warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
988
+ else
989
+ warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
990
+ end
991
+ pretty_generate(...)
834
992
  end
993
+ module_function :fast_unparse
835
994
 
836
- def merge_dump_options(opts, strict: NOT_SET)
837
- opts = opts.merge(strict: strict) if NOT_SET != strict
838
- opts
995
+ def restore(...)
996
+ if RUBY_VERSION >= "3.0"
997
+ warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated
998
+ else
999
+ warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1
1000
+ end
1001
+ load(...)
839
1002
  end
1003
+ module_function :restore
840
1004
 
841
1005
  class << self
842
- private :merge_dump_options
1006
+ private
1007
+
1008
+ def const_missing(const_name)
1009
+ case const_name
1010
+ when :PRETTY_STATE_PROTOTYPE
1011
+ if RUBY_VERSION >= "3.0"
1012
+ 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
1013
+ else
1014
+ warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
1015
+ end
1016
+ state.new(PRETTY_GENERATE_OPTIONS)
1017
+ else
1018
+ super
1019
+ end
1020
+ end
1021
+ end
1022
+ # :startdoc:
1023
+
1024
+ # JSON::Coder holds a parser and generator configuration.
1025
+ #
1026
+ # module MyApp
1027
+ # JSONC_CODER = JSON::Coder.new(
1028
+ # allow_trailing_comma: true
1029
+ # )
1030
+ # end
1031
+ #
1032
+ # MyApp::JSONC_CODER.load(document)
1033
+ #
1034
+ class Coder
1035
+ # :call-seq:
1036
+ # JSON.new(options = nil, &block)
1037
+ #
1038
+ # Argument +options+, if given, contains a \Hash of options for both parsing and generating.
1039
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
1040
+ #
1041
+ # For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
1042
+ # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
1043
+ # \JSON counterpart:
1044
+ #
1045
+ # module MyApp
1046
+ # API_JSON_CODER = JSON::Coder.new do |object|
1047
+ # case object
1048
+ # when Time
1049
+ # object.iso8601(3)
1050
+ # else
1051
+ # object # Unknown type, will raise
1052
+ # end
1053
+ # end
1054
+ # end
1055
+ #
1056
+ # puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
1057
+ #
1058
+ def initialize(options = nil, &as_json)
1059
+ if options.nil?
1060
+ options = { strict: true }
1061
+ else
1062
+ options = options.dup
1063
+ options[:strict] = true
1064
+ end
1065
+ options[:as_json] = as_json if as_json
1066
+
1067
+ @state = State.new(options).freeze
1068
+ @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
1069
+ end
1070
+
1071
+ # call-seq:
1072
+ # dump(object) -> String
1073
+ # dump(object, io) -> io
1074
+ #
1075
+ # Serialize the given object into a \JSON document.
1076
+ def dump(object, io = nil)
1077
+ @state.generate(object, io)
1078
+ end
1079
+ alias_method :generate, :dump
1080
+
1081
+ # call-seq:
1082
+ # load(string) -> Object
1083
+ #
1084
+ # Parse the given \JSON document and return an equivalent Ruby object.
1085
+ def load(source)
1086
+ @parser_config.parse(source)
1087
+ end
1088
+ alias_method :parse, :load
1089
+
1090
+ # call-seq:
1091
+ # load(path) -> Object
1092
+ #
1093
+ # Parse the given \JSON document and return an equivalent Ruby object.
1094
+ def load_file(path)
1095
+ load(File.read(path, encoding: Encoding::UTF_8))
1096
+ end
843
1097
  end
844
1098
  end
845
1099
 
@@ -849,8 +1103,14 @@ module ::Kernel
849
1103
  # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
850
1104
  # one line.
851
1105
  def j(*objs)
1106
+ if RUBY_VERSION >= "3.0"
1107
+ warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
1108
+ else
1109
+ warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
1110
+ end
1111
+
852
1112
  objs.each do |obj|
853
- puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
1113
+ puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
854
1114
  end
855
1115
  nil
856
1116
  end
@@ -858,8 +1118,14 @@ module ::Kernel
858
1118
  # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
859
1119
  # indentation and over many lines.
860
1120
  def jj(*objs)
1121
+ if RUBY_VERSION >= "3.0"
1122
+ warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
1123
+ else
1124
+ warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
1125
+ end
1126
+
861
1127
  objs.each do |obj|
862
- puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
1128
+ puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
863
1129
  end
864
1130
  nil
865
1131
  end
@@ -870,27 +1136,7 @@ module ::Kernel
870
1136
  #
871
1137
  # The _opts_ argument is passed through to generate/parse respectively. See
872
1138
  # generate and parse for their documentation.
873
- def JSON(object, *args)
874
- if object.is_a?(String)
875
- return JSON.parse(object, args.first)
876
- elsif object.respond_to?(:to_str)
877
- str = object.to_str
878
- if str.is_a?(String)
879
- return JSON.parse(object.to_str, args.first)
880
- end
881
- end
882
-
883
- JSON.generate(object, args.first)
884
- end
885
- end
886
-
887
- # Extends any Class to include _json_creatable?_ method.
888
- class ::Class
889
- # Returns true if this class can be used to create an instance
890
- # from a serialised JSON string. The class has to implement a class
891
- # method _json_create_ that expects a hash as first parameter. The hash
892
- # should include the required data.
893
- def json_creatable?
894
- respond_to?(:json_create)
1139
+ def JSON(object, opts = nil)
1140
+ JSON[object, opts]
895
1141
  end
896
1142
  end