json 2.21.2-java → 3.0.0-java
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.
- checksums.yaml +4 -4
- data/CHANGES.md +47 -1
- data/README.md +4 -84
- data/lib/json/common.rb +136 -403
- data/lib/json/ext/generator/state.rb +0 -27
- data/lib/json/ext/generator.jar +0 -0
- data/lib/json/ext/parser.jar +0 -0
- data/lib/json/ext.rb +0 -2
- data/lib/json/truffle_ruby/generator.rb +38 -80
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +13 -265
- metadata +2 -18
- data/lib/json/add/bigdecimal.rb +0 -58
- data/lib/json/add/complex.rb +0 -51
- data/lib/json/add/core.rb +0 -13
- data/lib/json/add/date.rb +0 -54
- data/lib/json/add/date_time.rb +0 -67
- data/lib/json/add/exception.rb +0 -49
- data/lib/json/add/ostruct.rb +0 -54
- data/lib/json/add/range.rb +0 -54
- data/lib/json/add/rational.rb +0 -49
- data/lib/json/add/regexp.rb +0 -48
- data/lib/json/add/set.rb +0 -48
- data/lib/json/add/string.rb +0 -35
- data/lib/json/add/struct.rb +0 -52
- data/lib/json/add/symbol.rb +0 -52
- data/lib/json/add/time.rb +0 -52
- data/lib/json/generic_object.rb +0 -67
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
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
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
|
-
|
|
368
|
-
|
|
369
|
-
|
|
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,
|
|
385
|
-
|
|
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,
|
|
321
|
+
# JSON.load_file(path, **) -> object
|
|
394
322
|
#
|
|
395
323
|
# Calls:
|
|
396
|
-
# parse(File.read(path),
|
|
324
|
+
# parse(File.read(path), **)
|
|
397
325
|
#
|
|
398
326
|
# See method #parse.
|
|
399
|
-
def load_file(filespec,
|
|
400
|
-
parse(File.read(filespec, encoding: Encoding::UTF_8),
|
|
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,
|
|
332
|
+
# JSON.load_file!(path, **)
|
|
405
333
|
#
|
|
406
334
|
# Calls:
|
|
407
|
-
# JSON.parse!(File.read(path,
|
|
335
|
+
# JSON.parse!(File.read(path), **)
|
|
408
336
|
#
|
|
409
337
|
# See method #parse!
|
|
410
|
-
def load_file!(filespec,
|
|
411
|
-
parse!(File.read(filespec, encoding: Encoding::UTF_8),
|
|
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
|
|
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
|
|
695
|
-
|
|
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,
|
|
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,30 +714,19 @@ module JSON
|
|
|
889
714
|
end
|
|
890
715
|
end
|
|
891
716
|
|
|
892
|
-
if
|
|
717
|
+
if allow_blank && (source.nil? || (String === source && source.empty?))
|
|
893
718
|
source = 'null'
|
|
894
719
|
end
|
|
895
720
|
|
|
896
721
|
if proc
|
|
897
|
-
|
|
898
|
-
|
|
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,
|
|
729
|
+
# JSON.dump(obj, io = 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
|
#
|
|
@@ -921,7 +735,6 @@ module JSON
|
|
|
921
735
|
# - Argument +io+, if given, should respond to method +write+;
|
|
922
736
|
# the \JSON \String is written to +io+, and +io+ is returned.
|
|
923
737
|
# 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
738
|
#
|
|
926
739
|
# ---
|
|
927
740
|
#
|
|
@@ -938,100 +751,26 @@ module JSON
|
|
|
938
751
|
# puts File.read(path)
|
|
939
752
|
# Output:
|
|
940
753
|
# {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
|
|
941
|
-
def dump(obj, anIO = nil,
|
|
754
|
+
def dump(obj, anIO = nil, kwargs = nil)
|
|
942
755
|
if kwargs.nil?
|
|
943
|
-
if
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
anIO = nil
|
|
947
|
-
end
|
|
948
|
-
elsif limit.is_a?(Hash)
|
|
949
|
-
kwargs = limit
|
|
950
|
-
limit = nil
|
|
756
|
+
if anIO.is_a?(Hash)
|
|
757
|
+
kwargs = anIO
|
|
758
|
+
anIO = nil
|
|
951
759
|
end
|
|
952
760
|
end
|
|
953
761
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
anIO = anIO.to_io
|
|
957
|
-
elsif limit.nil? && !anIO.respond_to?(:write)
|
|
958
|
-
anIO, limit = nil, anIO
|
|
959
|
-
end
|
|
762
|
+
if anIO&.respond_to?(:to_io)
|
|
763
|
+
anIO = anIO.to_io
|
|
960
764
|
end
|
|
961
765
|
|
|
962
|
-
opts =
|
|
963
|
-
|
|
964
|
-
|
|
766
|
+
opts = {
|
|
767
|
+
allow_nan: true,
|
|
768
|
+
}
|
|
769
|
+
opts.merge!(kwargs) if kwargs
|
|
965
770
|
|
|
966
|
-
|
|
967
|
-
State.generate(obj, opts, anIO)
|
|
968
|
-
rescue JSON::NestingError
|
|
969
|
-
raise ArgumentError, "exceed depth limit"
|
|
970
|
-
end
|
|
771
|
+
State.generate(obj, opts, anIO)
|
|
971
772
|
end
|
|
972
773
|
|
|
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
774
|
# JSON::Coder holds a parser and generator configuration.
|
|
1036
775
|
#
|
|
1037
776
|
# module MyApp
|
|
@@ -1043,6 +782,27 @@ module JSON
|
|
|
1043
782
|
# MyApp::JSONC_CODER.load(document)
|
|
1044
783
|
#
|
|
1045
784
|
class Coder
|
|
785
|
+
PARSER_OPTIONS = %i(
|
|
786
|
+
max_nesting
|
|
787
|
+
allow_nan
|
|
788
|
+
allow_trailing_comma
|
|
789
|
+
allow_comments
|
|
790
|
+
allow_control_characters
|
|
791
|
+
allow_invalid_escape
|
|
792
|
+
symbolize_names
|
|
793
|
+
freeze
|
|
794
|
+
allow_duplicate_key
|
|
795
|
+
decimal_class
|
|
796
|
+
).freeze
|
|
797
|
+
private_constant :PARSER_OPTIONS
|
|
798
|
+
|
|
799
|
+
EXCLUDED_GENERATOR_OPTIONS = (PARSER_OPTIONS - %i(
|
|
800
|
+
max_nesting
|
|
801
|
+
allow_nan
|
|
802
|
+
allow_duplicate_key
|
|
803
|
+
)).freeze
|
|
804
|
+
private_constant :EXCLUDED_GENERATOR_OPTIONS
|
|
805
|
+
|
|
1046
806
|
# :call-seq:
|
|
1047
807
|
# JSON.new(options = nil, &block)
|
|
1048
808
|
#
|
|
@@ -1067,17 +827,20 @@ module JSON
|
|
|
1067
827
|
#
|
|
1068
828
|
# puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
|
|
1069
829
|
#
|
|
1070
|
-
def initialize(
|
|
1071
|
-
if
|
|
1072
|
-
|
|
1073
|
-
else
|
|
1074
|
-
options = options.dup
|
|
1075
|
-
options[:strict] = true
|
|
830
|
+
def initialize(object_class: nil, array_class: nil, on_load: nil, **options, &as_json)
|
|
831
|
+
if object_class || array_class
|
|
832
|
+
on_load = ParserOptions.on_load(on_load, object_class, array_class)
|
|
1076
833
|
end
|
|
1077
|
-
|
|
834
|
+
parser_options = options.slice(*PARSER_OPTIONS)
|
|
835
|
+
parser_options[:on_load] = on_load if on_load
|
|
836
|
+
@parser_config = Ext::Parser::Config.new(parser_options).freeze
|
|
1078
837
|
|
|
1079
|
-
|
|
1080
|
-
@
|
|
838
|
+
generator_options = options.reject { |k, _| EXCLUDED_GENERATOR_OPTIONS.include?(k) }
|
|
839
|
+
@state = State.new(
|
|
840
|
+
**generator_options,
|
|
841
|
+
strict: true,
|
|
842
|
+
as_json: as_json,
|
|
843
|
+
).freeze
|
|
1081
844
|
end
|
|
1082
845
|
|
|
1083
846
|
# call-seq:
|
|
@@ -1136,36 +899,6 @@ end
|
|
|
1136
899
|
module ::Kernel
|
|
1137
900
|
private
|
|
1138
901
|
|
|
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
902
|
# If _object_ is string-like, parse the string and return the parsed result as
|
|
1170
903
|
# a Ruby data structure. Otherwise, generate a JSON text from the Ruby data
|
|
1171
904
|
# structure object and return it.
|