json 2.10.2 → 2.19.9
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 +205 -7
- data/LEGAL +12 -0
- data/README.md +43 -1
- data/ext/json/ext/fbuffer/fbuffer.h +140 -86
- data/ext/json/ext/generator/extconf.rb +8 -0
- data/ext/json/ext/generator/generator.c +787 -616
- data/ext/json/ext/json.h +116 -0
- data/ext/json/ext/parser/extconf.rb +11 -3
- data/ext/json/ext/parser/parser.c +974 -703
- data/ext/json/ext/simd/conf.rb +24 -0
- data/ext/json/ext/simd/simd.h +208 -0
- data/ext/json/ext/vendor/fpconv.c +480 -0
- data/ext/json/ext/vendor/jeaiii-ltoa.h +267 -0
- data/ext/json/ext/vendor/ryu.h +819 -0
- data/json.gemspec +2 -3
- data/lib/json/add/core.rb +1 -0
- data/lib/json/add/string.rb +35 -0
- data/lib/json/common.rb +374 -188
- data/lib/json/ext/generator/state.rb +11 -14
- data/lib/json/ext.rb +2 -2
- data/lib/json/generic_object.rb +0 -8
- data/lib/json/truffle_ruby/generator.rb +137 -72
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +90 -2
- metadata +66 -57
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
|
-
|
|
9
|
-
|
|
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,64 +152,76 @@ 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
|
|
59
158
|
@generator = generator
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
159
|
+
if generator.const_defined?(:GeneratorMethods)
|
|
160
|
+
generator_methods = generator::GeneratorMethods
|
|
161
|
+
for const in generator_methods.constants
|
|
162
|
+
klass = const_get(const)
|
|
163
|
+
modul = generator_methods.const_get(const)
|
|
164
|
+
klass.class_eval do
|
|
165
|
+
instance_methods(false).each do |m|
|
|
166
|
+
m.to_s == 'to_json' and remove_method m
|
|
167
|
+
end
|
|
168
|
+
include modul
|
|
67
169
|
end
|
|
68
|
-
include modul
|
|
69
170
|
end
|
|
70
171
|
end
|
|
71
172
|
self.state = generator::State
|
|
72
|
-
const_set :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
|
|
173
|
+
const_set :State, state
|
|
76
174
|
ensure
|
|
77
175
|
$VERBOSE = old
|
|
78
176
|
end
|
|
79
177
|
|
|
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
178
|
# Returns the JSON generator module that is used by JSON.
|
|
100
179
|
attr_reader :generator
|
|
101
180
|
|
|
102
181
|
# Sets or Returns the JSON generator state class that is used by JSON.
|
|
103
182
|
attr_accessor :state
|
|
183
|
+
|
|
184
|
+
private
|
|
185
|
+
|
|
186
|
+
# Called from the extension when a hash has both string and symbol keys
|
|
187
|
+
def on_mixed_keys_hash(hash, do_raise)
|
|
188
|
+
set = {}
|
|
189
|
+
hash.each_key do |key|
|
|
190
|
+
key_str = key.to_s
|
|
191
|
+
|
|
192
|
+
if set[key_str]
|
|
193
|
+
message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
|
|
194
|
+
if do_raise
|
|
195
|
+
raise GeneratorError, message
|
|
196
|
+
else
|
|
197
|
+
deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
|
|
198
|
+
end
|
|
199
|
+
else
|
|
200
|
+
set[key_str] = true
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def deprecated_singleton_attr_accessor(*attrs)
|
|
206
|
+
args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
|
|
207
|
+
attrs.each do |attr|
|
|
208
|
+
singleton_class.class_eval <<~RUBY
|
|
209
|
+
def #{attr}
|
|
210
|
+
warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
|
|
211
|
+
@#{attr}
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def #{attr}=(val)
|
|
215
|
+
warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
|
|
216
|
+
@#{attr} = val
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def _#{attr}
|
|
220
|
+
@#{attr}
|
|
221
|
+
end
|
|
222
|
+
RUBY
|
|
223
|
+
end
|
|
224
|
+
end
|
|
104
225
|
end
|
|
105
226
|
|
|
106
227
|
# Sets create identifier, which is used to decide if the _json_create_
|
|
@@ -116,32 +237,24 @@ module JSON
|
|
|
116
237
|
Thread.current[:"JSON.create_id"] || 'json_class'
|
|
117
238
|
end
|
|
118
239
|
|
|
119
|
-
NaN =
|
|
240
|
+
NaN = Float::NAN
|
|
120
241
|
|
|
121
|
-
Infinity =
|
|
242
|
+
Infinity = Float::INFINITY
|
|
122
243
|
|
|
123
244
|
MinusInfinity = -Infinity
|
|
124
245
|
|
|
125
246
|
# 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
|
|
247
|
+
class JSONError < StandardError; end
|
|
133
248
|
|
|
134
249
|
# This exception is raised if a parser error occurs.
|
|
135
|
-
class ParserError < JSONError
|
|
250
|
+
class ParserError < JSONError
|
|
251
|
+
attr_reader :line, :column
|
|
252
|
+
end
|
|
136
253
|
|
|
137
254
|
# This exception is raised if the nesting of parsed data structures is too
|
|
138
255
|
# deep.
|
|
139
256
|
class NestingError < ParserError; end
|
|
140
257
|
|
|
141
|
-
# :stopdoc:
|
|
142
|
-
class CircularDatastructure < NestingError; end
|
|
143
|
-
# :startdoc:
|
|
144
|
-
|
|
145
258
|
# This exception is raised if a generator or unparser error occurs.
|
|
146
259
|
class GeneratorError < JSONError
|
|
147
260
|
attr_reader :invalid_object
|
|
@@ -163,13 +276,6 @@ module JSON
|
|
|
163
276
|
end
|
|
164
277
|
end
|
|
165
278
|
|
|
166
|
-
# For backwards compatibility
|
|
167
|
-
UnparserError = GeneratorError # :nodoc:
|
|
168
|
-
|
|
169
|
-
# This exception is raised if the required unicode support is missing on the
|
|
170
|
-
# system. Usually this means that the iconv library is not installed.
|
|
171
|
-
class MissingUnicodeSupport < JSONError; end
|
|
172
|
-
|
|
173
279
|
# Fragment of JSON document that is to be included as is:
|
|
174
280
|
# fragment = JSON::Fragment.new("[1, 2, 3]")
|
|
175
281
|
# JSON.generate({ count: 3, items: fragments })
|
|
@@ -179,7 +285,7 @@ module JSON
|
|
|
179
285
|
# to string interpolation.
|
|
180
286
|
#
|
|
181
287
|
# Note: no validation is performed on the provided string. It is the
|
|
182
|
-
#
|
|
288
|
+
# responsibility of the caller to ensure the string contains valid JSON.
|
|
183
289
|
Fragment = Struct.new(:json) do
|
|
184
290
|
def initialize(json)
|
|
185
291
|
unless string = String.try_convert(json)
|
|
@@ -245,9 +351,16 @@ module JSON
|
|
|
245
351
|
# JSON.parse('')
|
|
246
352
|
#
|
|
247
353
|
def parse(source, opts = nil)
|
|
354
|
+
opts = ParserOptions.prepare(opts) unless opts.nil?
|
|
248
355
|
Parser.parse(source, opts)
|
|
249
356
|
end
|
|
250
357
|
|
|
358
|
+
PARSE_L_OPTIONS = {
|
|
359
|
+
max_nesting: false,
|
|
360
|
+
allow_nan: true,
|
|
361
|
+
}.freeze
|
|
362
|
+
private_constant :PARSE_L_OPTIONS
|
|
363
|
+
|
|
251
364
|
# :call-seq:
|
|
252
365
|
# JSON.parse!(source, opts) -> object
|
|
253
366
|
#
|
|
@@ -260,12 +373,11 @@ module JSON
|
|
|
260
373
|
# which disables checking for nesting depth.
|
|
261
374
|
# - Option +allow_nan+, if not provided, defaults to +true+.
|
|
262
375
|
def parse!(source, opts = nil)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
Parser.new(source, options).parse
|
|
376
|
+
if opts.nil?
|
|
377
|
+
parse(source, PARSE_L_OPTIONS)
|
|
378
|
+
else
|
|
379
|
+
parse(source, PARSE_L_OPTIONS.merge(opts))
|
|
380
|
+
end
|
|
269
381
|
end
|
|
270
382
|
|
|
271
383
|
# :call-seq:
|
|
@@ -295,7 +407,7 @@ module JSON
|
|
|
295
407
|
#
|
|
296
408
|
# Returns a \String containing the generated \JSON data.
|
|
297
409
|
#
|
|
298
|
-
# See also JSON.
|
|
410
|
+
# See also JSON.pretty_generate.
|
|
299
411
|
#
|
|
300
412
|
# Argument +obj+ is the Ruby object to be converted to \JSON.
|
|
301
413
|
#
|
|
@@ -334,13 +446,6 @@ module JSON
|
|
|
334
446
|
end
|
|
335
447
|
end
|
|
336
448
|
|
|
337
|
-
# :stopdoc:
|
|
338
|
-
# I want to deprecate these later, so I'll first be silent about them, and
|
|
339
|
-
# later delete them.
|
|
340
|
-
alias unparse generate
|
|
341
|
-
module_function :unparse
|
|
342
|
-
# :startdoc:
|
|
343
|
-
|
|
344
449
|
# :call-seq:
|
|
345
450
|
# JSON.fast_generate(obj, opts) -> new_string
|
|
346
451
|
#
|
|
@@ -355,19 +460,21 @@ module JSON
|
|
|
355
460
|
# # Raises SystemStackError (stack level too deep):
|
|
356
461
|
# JSON.fast_generate(a)
|
|
357
462
|
def fast_generate(obj, opts = nil)
|
|
358
|
-
if
|
|
359
|
-
|
|
463
|
+
if RUBY_VERSION >= "3.0"
|
|
464
|
+
warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
|
|
360
465
|
else
|
|
361
|
-
|
|
466
|
+
warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
|
|
362
467
|
end
|
|
363
|
-
|
|
468
|
+
generate(obj, opts)
|
|
364
469
|
end
|
|
365
470
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
471
|
+
PRETTY_GENERATE_OPTIONS = {
|
|
472
|
+
indent: ' ',
|
|
473
|
+
space: ' ',
|
|
474
|
+
object_nl: "\n",
|
|
475
|
+
array_nl: "\n",
|
|
476
|
+
}.freeze
|
|
477
|
+
private_constant :PRETTY_GENERATE_OPTIONS
|
|
371
478
|
|
|
372
479
|
# :call-seq:
|
|
373
480
|
# JSON.pretty_generate(obj, opts = nil) -> new_string
|
|
@@ -400,57 +507,52 @@ module JSON
|
|
|
400
507
|
# }
|
|
401
508
|
#
|
|
402
509
|
def pretty_generate(obj, opts = nil)
|
|
403
|
-
if State === opts
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
end
|
|
510
|
+
return opts.generate(obj) if State === opts
|
|
511
|
+
|
|
512
|
+
options = PRETTY_GENERATE_OPTIONS
|
|
513
|
+
|
|
408
514
|
if opts
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
515
|
+
unless opts.is_a?(Hash)
|
|
516
|
+
if opts.respond_to? :to_hash
|
|
517
|
+
opts = opts.to_hash
|
|
518
|
+
elsif opts.respond_to? :to_h
|
|
519
|
+
opts = opts.to_h
|
|
520
|
+
else
|
|
521
|
+
raise TypeError, "can't convert #{opts.class} into Hash"
|
|
522
|
+
end
|
|
415
523
|
end
|
|
416
|
-
|
|
524
|
+
options = options.merge(opts)
|
|
417
525
|
end
|
|
418
|
-
|
|
526
|
+
|
|
527
|
+
State.generate(obj, options, nil)
|
|
419
528
|
end
|
|
420
529
|
|
|
421
|
-
#
|
|
422
|
-
#
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
530
|
+
# Sets or returns default options for the JSON.unsafe_load method.
|
|
531
|
+
# Initially:
|
|
532
|
+
# opts = JSON.load_default_options
|
|
533
|
+
# opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
|
|
534
|
+
deprecated_singleton_attr_accessor :unsafe_load_default_options
|
|
426
535
|
|
|
427
|
-
|
|
428
|
-
# Sets or returns default options for the JSON.unsafe_load method.
|
|
429
|
-
# Initially:
|
|
430
|
-
# opts = JSON.load_default_options
|
|
431
|
-
# opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
|
|
432
|
-
attr_accessor :unsafe_load_default_options
|
|
433
|
-
end
|
|
434
|
-
self.unsafe_load_default_options = {
|
|
536
|
+
@unsafe_load_default_options = {
|
|
435
537
|
:max_nesting => false,
|
|
436
538
|
:allow_nan => true,
|
|
437
539
|
:allow_blank => true,
|
|
438
540
|
:create_additions => true,
|
|
439
541
|
}
|
|
440
542
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
self.load_default_options = {
|
|
543
|
+
# Sets or returns default options for the JSON.load method.
|
|
544
|
+
# Initially:
|
|
545
|
+
# opts = JSON.load_default_options
|
|
546
|
+
# opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
|
|
547
|
+
deprecated_singleton_attr_accessor :load_default_options
|
|
548
|
+
|
|
549
|
+
@load_default_options = {
|
|
449
550
|
:allow_nan => true,
|
|
450
551
|
:allow_blank => true,
|
|
451
552
|
:create_additions => nil,
|
|
452
553
|
}
|
|
453
554
|
# :call-seq:
|
|
555
|
+
# JSON.unsafe_load(source, options = {}) -> object
|
|
454
556
|
# JSON.unsafe_load(source, proc = nil, options = {}) -> object
|
|
455
557
|
#
|
|
456
558
|
# Returns the Ruby objects created by parsing the given +source+.
|
|
@@ -558,6 +660,7 @@ module JSON
|
|
|
558
660
|
# when Array
|
|
559
661
|
# obj.map! {|v| deserialize_obj v }
|
|
560
662
|
# end
|
|
663
|
+
# obj
|
|
561
664
|
# })
|
|
562
665
|
# pp ruby
|
|
563
666
|
# Output:
|
|
@@ -581,9 +684,14 @@ module JSON
|
|
|
581
684
|
#
|
|
582
685
|
def unsafe_load(source, proc = nil, options = nil)
|
|
583
686
|
opts = if options.nil?
|
|
584
|
-
|
|
687
|
+
if proc && proc.is_a?(Hash)
|
|
688
|
+
options, proc = proc, nil
|
|
689
|
+
options
|
|
690
|
+
else
|
|
691
|
+
_unsafe_load_default_options
|
|
692
|
+
end
|
|
585
693
|
else
|
|
586
|
-
|
|
694
|
+
_unsafe_load_default_options.merge(options)
|
|
587
695
|
end
|
|
588
696
|
|
|
589
697
|
unless source.is_a?(String)
|
|
@@ -599,12 +707,17 @@ module JSON
|
|
|
599
707
|
if opts[:allow_blank] && (source.nil? || source.empty?)
|
|
600
708
|
source = 'null'
|
|
601
709
|
end
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
710
|
+
|
|
711
|
+
if proc
|
|
712
|
+
opts = opts.dup
|
|
713
|
+
opts[:on_load] = proc.to_proc
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
parse(source, opts)
|
|
605
717
|
end
|
|
606
718
|
|
|
607
719
|
# :call-seq:
|
|
720
|
+
# JSON.load(source, options = {}) -> object
|
|
608
721
|
# JSON.load(source, proc = nil, options = {}) -> object
|
|
609
722
|
#
|
|
610
723
|
# Returns the Ruby objects created by parsing the given +source+.
|
|
@@ -718,6 +831,7 @@ module JSON
|
|
|
718
831
|
# when Array
|
|
719
832
|
# obj.map! {|v| deserialize_obj v }
|
|
720
833
|
# end
|
|
834
|
+
# obj
|
|
721
835
|
# })
|
|
722
836
|
# pp ruby
|
|
723
837
|
# Output:
|
|
@@ -740,10 +854,20 @@ module JSON
|
|
|
740
854
|
# @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
|
|
741
855
|
#
|
|
742
856
|
def load(source, proc = nil, options = nil)
|
|
857
|
+
if proc && options.nil? && proc.is_a?(Hash)
|
|
858
|
+
options = proc
|
|
859
|
+
proc = nil
|
|
860
|
+
end
|
|
861
|
+
|
|
743
862
|
opts = if options.nil?
|
|
744
|
-
|
|
863
|
+
if proc && proc.is_a?(Hash)
|
|
864
|
+
options, proc = proc, nil
|
|
865
|
+
options
|
|
866
|
+
else
|
|
867
|
+
_load_default_options
|
|
868
|
+
end
|
|
745
869
|
else
|
|
746
|
-
|
|
870
|
+
_load_default_options.merge(options)
|
|
747
871
|
end
|
|
748
872
|
|
|
749
873
|
unless source.is_a?(String)
|
|
@@ -756,39 +880,24 @@ module JSON
|
|
|
756
880
|
end
|
|
757
881
|
end
|
|
758
882
|
|
|
759
|
-
if opts[:allow_blank] && (source.nil? || source.empty?)
|
|
883
|
+
if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
|
|
760
884
|
source = 'null'
|
|
761
885
|
end
|
|
762
|
-
result = parse(source, opts)
|
|
763
|
-
recurse_proc(result, &proc) if proc
|
|
764
|
-
result
|
|
765
|
-
end
|
|
766
886
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
when Array
|
|
771
|
-
result.each { |x| recurse_proc x, &proc }
|
|
772
|
-
proc.call result
|
|
773
|
-
when Hash
|
|
774
|
-
result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
|
|
775
|
-
proc.call result
|
|
776
|
-
else
|
|
777
|
-
proc.call result
|
|
887
|
+
if proc
|
|
888
|
+
opts = opts.dup
|
|
889
|
+
opts[:on_load] = proc.to_proc
|
|
778
890
|
end
|
|
779
|
-
end
|
|
780
|
-
|
|
781
|
-
alias restore load
|
|
782
|
-
module_function :restore
|
|
783
891
|
|
|
784
|
-
|
|
785
|
-
# Sets or returns the default options for the JSON.dump method.
|
|
786
|
-
# Initially:
|
|
787
|
-
# opts = JSON.dump_default_options
|
|
788
|
-
# opts # => {:max_nesting=>false, :allow_nan=>true}
|
|
789
|
-
attr_accessor :dump_default_options
|
|
892
|
+
parse(source, opts)
|
|
790
893
|
end
|
|
791
|
-
|
|
894
|
+
|
|
895
|
+
# Sets or returns the default options for the JSON.dump method.
|
|
896
|
+
# Initially:
|
|
897
|
+
# opts = JSON.dump_default_options
|
|
898
|
+
# opts # => {:max_nesting=>false, :allow_nan=>true}
|
|
899
|
+
deprecated_singleton_attr_accessor :dump_default_options
|
|
900
|
+
@dump_default_options = {
|
|
792
901
|
:max_nesting => false,
|
|
793
902
|
:allow_nan => true,
|
|
794
903
|
}
|
|
@@ -841,7 +950,7 @@ module JSON
|
|
|
841
950
|
end
|
|
842
951
|
end
|
|
843
952
|
|
|
844
|
-
opts = JSON.
|
|
953
|
+
opts = JSON._dump_default_options
|
|
845
954
|
opts = opts.merge(:max_nesting => limit) if limit
|
|
846
955
|
opts = opts.merge(kwargs) if kwargs
|
|
847
956
|
|
|
@@ -852,10 +961,67 @@ module JSON
|
|
|
852
961
|
end
|
|
853
962
|
end
|
|
854
963
|
|
|
855
|
-
#
|
|
856
|
-
|
|
857
|
-
|
|
964
|
+
# :stopdoc:
|
|
965
|
+
# All these were meant to be deprecated circa 2009, but were just set as undocumented
|
|
966
|
+
# so usage still exist in the wild.
|
|
967
|
+
def unparse(...)
|
|
968
|
+
if RUBY_VERSION >= "3.0"
|
|
969
|
+
warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
|
|
970
|
+
else
|
|
971
|
+
warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
|
|
972
|
+
end
|
|
973
|
+
generate(...)
|
|
974
|
+
end
|
|
975
|
+
module_function :unparse
|
|
976
|
+
|
|
977
|
+
def fast_unparse(...)
|
|
978
|
+
if RUBY_VERSION >= "3.0"
|
|
979
|
+
warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
|
|
980
|
+
else
|
|
981
|
+
warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
|
|
982
|
+
end
|
|
983
|
+
generate(...)
|
|
984
|
+
end
|
|
985
|
+
module_function :fast_unparse
|
|
986
|
+
|
|
987
|
+
def pretty_unparse(...)
|
|
988
|
+
if RUBY_VERSION >= "3.0"
|
|
989
|
+
warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
|
|
990
|
+
else
|
|
991
|
+
warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
|
|
992
|
+
end
|
|
993
|
+
pretty_generate(...)
|
|
994
|
+
end
|
|
995
|
+
module_function :fast_unparse
|
|
996
|
+
|
|
997
|
+
def restore(...)
|
|
998
|
+
if RUBY_VERSION >= "3.0"
|
|
999
|
+
warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated
|
|
1000
|
+
else
|
|
1001
|
+
warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1
|
|
1002
|
+
end
|
|
1003
|
+
load(...)
|
|
858
1004
|
end
|
|
1005
|
+
module_function :restore
|
|
1006
|
+
|
|
1007
|
+
class << self
|
|
1008
|
+
private
|
|
1009
|
+
|
|
1010
|
+
def const_missing(const_name)
|
|
1011
|
+
case const_name
|
|
1012
|
+
when :PRETTY_STATE_PROTOTYPE
|
|
1013
|
+
if RUBY_VERSION >= "3.0"
|
|
1014
|
+
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
|
|
1015
|
+
else
|
|
1016
|
+
warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
|
|
1017
|
+
end
|
|
1018
|
+
state.new(PRETTY_GENERATE_OPTIONS)
|
|
1019
|
+
else
|
|
1020
|
+
super
|
|
1021
|
+
end
|
|
1022
|
+
end
|
|
1023
|
+
end
|
|
1024
|
+
# :startdoc:
|
|
859
1025
|
|
|
860
1026
|
# JSON::Coder holds a parser and generator configuration.
|
|
861
1027
|
#
|
|
@@ -872,10 +1038,11 @@ module JSON
|
|
|
872
1038
|
# JSON.new(options = nil, &block)
|
|
873
1039
|
#
|
|
874
1040
|
# Argument +options+, if given, contains a \Hash of options for both parsing and generating.
|
|
875
|
-
# See {Parsing Options}[
|
|
1041
|
+
# See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
|
|
1042
|
+
# and {Generating Options}[rdoc-ref:JSON@Generating+Options].
|
|
876
1043
|
#
|
|
877
1044
|
# For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
|
|
878
|
-
#
|
|
1045
|
+
# encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
|
|
879
1046
|
# \JSON counterpart:
|
|
880
1047
|
#
|
|
881
1048
|
# module MyApp
|
|
@@ -899,10 +1066,9 @@ module JSON
|
|
|
899
1066
|
options[:strict] = true
|
|
900
1067
|
end
|
|
901
1068
|
options[:as_json] = as_json if as_json
|
|
902
|
-
options[:create_additions] = false unless options.key?(:create_additions)
|
|
903
1069
|
|
|
904
1070
|
@state = State.new(options).freeze
|
|
905
|
-
@parser_config = Ext::Parser::Config.new(options)
|
|
1071
|
+
@parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
|
|
906
1072
|
end
|
|
907
1073
|
|
|
908
1074
|
# call-seq:
|
|
@@ -911,7 +1077,7 @@ module JSON
|
|
|
911
1077
|
#
|
|
912
1078
|
# Serialize the given object into a \JSON document.
|
|
913
1079
|
def dump(object, io = nil)
|
|
914
|
-
@state.
|
|
1080
|
+
@state.generate(object, io)
|
|
915
1081
|
end
|
|
916
1082
|
alias_method :generate, :dump
|
|
917
1083
|
|
|
@@ -932,6 +1098,30 @@ module JSON
|
|
|
932
1098
|
load(File.read(path, encoding: Encoding::UTF_8))
|
|
933
1099
|
end
|
|
934
1100
|
end
|
|
1101
|
+
|
|
1102
|
+
module GeneratorMethods
|
|
1103
|
+
# call-seq: to_json(*)
|
|
1104
|
+
#
|
|
1105
|
+
# Converts this object into a JSON string.
|
|
1106
|
+
# If this object doesn't directly maps to a JSON native type,
|
|
1107
|
+
# first convert it to a string (calling #to_s), then converts
|
|
1108
|
+
# it to a JSON string, and returns the result.
|
|
1109
|
+
# This is a fallback, if no special method #to_json was defined for some object.
|
|
1110
|
+
def to_json(state = nil, *)
|
|
1111
|
+
obj = case self
|
|
1112
|
+
when nil, false, true, Integer, Float, Array, Hash
|
|
1113
|
+
self
|
|
1114
|
+
else
|
|
1115
|
+
"#{self}"
|
|
1116
|
+
end
|
|
1117
|
+
|
|
1118
|
+
if state.nil?
|
|
1119
|
+
JSON::State._generate_no_fallback(obj, nil, nil)
|
|
1120
|
+
else
|
|
1121
|
+
JSON::State.from_state(state)._generate_no_fallback(obj)
|
|
1122
|
+
end
|
|
1123
|
+
end
|
|
1124
|
+
end
|
|
935
1125
|
end
|
|
936
1126
|
|
|
937
1127
|
module ::Kernel
|
|
@@ -940,8 +1130,14 @@ module ::Kernel
|
|
|
940
1130
|
# Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
|
|
941
1131
|
# one line.
|
|
942
1132
|
def j(*objs)
|
|
1133
|
+
if RUBY_VERSION >= "3.0"
|
|
1134
|
+
warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
|
|
1135
|
+
else
|
|
1136
|
+
warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
|
|
1137
|
+
end
|
|
1138
|
+
|
|
943
1139
|
objs.each do |obj|
|
|
944
|
-
puts JSON
|
|
1140
|
+
puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
|
|
945
1141
|
end
|
|
946
1142
|
nil
|
|
947
1143
|
end
|
|
@@ -949,8 +1145,14 @@ module ::Kernel
|
|
|
949
1145
|
# Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
|
|
950
1146
|
# indentation and over many lines.
|
|
951
1147
|
def jj(*objs)
|
|
1148
|
+
if RUBY_VERSION >= "3.0"
|
|
1149
|
+
warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
|
|
1150
|
+
else
|
|
1151
|
+
warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
|
|
1152
|
+
end
|
|
1153
|
+
|
|
952
1154
|
objs.each do |obj|
|
|
953
|
-
puts JSON
|
|
1155
|
+
puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
|
|
954
1156
|
end
|
|
955
1157
|
nil
|
|
956
1158
|
end
|
|
@@ -961,27 +1163,11 @@ module ::Kernel
|
|
|
961
1163
|
#
|
|
962
1164
|
# The _opts_ argument is passed through to generate/parse respectively. See
|
|
963
1165
|
# generate and parse for their documentation.
|
|
964
|
-
def JSON(object,
|
|
965
|
-
|
|
966
|
-
return JSON.parse(object, args.first)
|
|
967
|
-
elsif object.respond_to?(:to_str)
|
|
968
|
-
str = object.to_str
|
|
969
|
-
if str.is_a?(String)
|
|
970
|
-
return JSON.parse(object.to_str, args.first)
|
|
971
|
-
end
|
|
972
|
-
end
|
|
973
|
-
|
|
974
|
-
JSON.generate(object, args.first)
|
|
1166
|
+
def JSON(object, opts = nil)
|
|
1167
|
+
JSON[object, opts]
|
|
975
1168
|
end
|
|
976
1169
|
end
|
|
977
1170
|
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
# Returns true if this class can be used to create an instance
|
|
981
|
-
# from a serialised JSON string. The class has to implement a class
|
|
982
|
-
# method _json_create_ that expects a hash as first parameter. The hash
|
|
983
|
-
# should include the required data.
|
|
984
|
-
def json_creatable?
|
|
985
|
-
respond_to?(:json_create)
|
|
986
|
-
end
|
|
1171
|
+
class Object
|
|
1172
|
+
include JSON::GeneratorMethods
|
|
987
1173
|
end
|