json 2.21.2 → 3.1.0
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 +64 -1
- data/README.md +4 -84
- data/ext/json/ext/fbuffer/fbuffer.h +4 -0
- data/ext/json/ext/generator/generator.c +187 -81
- data/ext/json/ext/json.h +19 -0
- data/ext/json/ext/parser/parser.c +139 -138
- data/lib/json/common.rb +153 -412
- data/lib/json/ext/generator/state.rb +2 -33
- data/lib/json/ext.rb +129 -5
- data/lib/json/truffle_ruby/generator.rb +140 -102
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +51 -295
- 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
|
@@ -54,7 +54,8 @@ module JSON
|
|
|
54
54
|
strict: strict?,
|
|
55
55
|
depth: depth,
|
|
56
56
|
buffer_initial_length: buffer_initial_length,
|
|
57
|
-
sort_keys: sort_keys
|
|
57
|
+
sort_keys: sort_keys,
|
|
58
|
+
rfc8785: rfc8785?,
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
allow_duplicate_key = allow_duplicate_key?
|
|
@@ -62,42 +63,10 @@ module JSON
|
|
|
62
63
|
result[:allow_duplicate_key] = allow_duplicate_key
|
|
63
64
|
end
|
|
64
65
|
|
|
65
|
-
instance_variables.each do |iv|
|
|
66
|
-
iv = iv.to_s[1..-1]
|
|
67
|
-
result[iv.to_sym] = self[iv]
|
|
68
|
-
end
|
|
69
|
-
|
|
70
66
|
result
|
|
71
67
|
end
|
|
72
68
|
|
|
73
69
|
alias_method :to_hash, :to_h
|
|
74
|
-
|
|
75
|
-
# call-seq: [](name)
|
|
76
|
-
#
|
|
77
|
-
# Returns the value returned by method +name+.
|
|
78
|
-
def [](name)
|
|
79
|
-
::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
|
|
80
|
-
|
|
81
|
-
if respond_to?(name)
|
|
82
|
-
__send__(name)
|
|
83
|
-
else
|
|
84
|
-
instance_variable_get("@#{name}") if
|
|
85
|
-
instance_variables.include?("@#{name}".to_sym) # avoid warning
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# call-seq: []=(name, value)
|
|
90
|
-
#
|
|
91
|
-
# Sets the attribute name to value.
|
|
92
|
-
def []=(name, value)
|
|
93
|
-
::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
|
|
94
|
-
|
|
95
|
-
if respond_to?(name_writer = "#{name}=")
|
|
96
|
-
__send__ name_writer, value
|
|
97
|
-
else
|
|
98
|
-
instance_variable_set "@#{name}", value
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
70
|
end
|
|
102
71
|
end
|
|
103
72
|
end
|
data/lib/json/ext.rb
CHANGED
|
@@ -28,17 +28,143 @@ module JSON
|
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
class << self
|
|
32
|
+
if defined?(::Ractor) && Ractor.respond_to?(:shareable_lambda)
|
|
33
|
+
def shareable_lambda(block) # :nodoc:
|
|
34
|
+
Ractor.shareable_lambda(&block)
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
def shareable_lambda(block) # :nodoc:
|
|
38
|
+
block
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def valid_encoding?(str) # :nodoc:
|
|
43
|
+
str.ascii_only? || (str.encoding == Encoding::UTF_8 && str.valid_encoding?)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def coerce_key(key, as_json) # :nodoc:
|
|
47
|
+
as_json_called = false
|
|
48
|
+
|
|
49
|
+
unless String === key || Symbol === key
|
|
50
|
+
key = as_json.call(key, true)
|
|
51
|
+
as_json_called = true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if Symbol === key
|
|
55
|
+
key = key.to_s
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
unless String === key
|
|
59
|
+
raise GeneratorError.new("#{key.class} not allowed as object key in JSON", key)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
unless valid_encoding?(key)
|
|
63
|
+
if as_json_called
|
|
64
|
+
raise GeneratorError.new("source sequence is illegal/malformed utf-8", key)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
key = as_json.call(key, true)
|
|
68
|
+
unless String === key
|
|
69
|
+
raise GeneratorError.new("#{key.class} not allowed as object key in JSON", key)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
unless Ext.valid_encoding?(key)
|
|
73
|
+
raise GeneratorError.new("source sequence is illegal/malformed utf-8", key)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
key
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def on_duplicate_key(hash, as_json)
|
|
81
|
+
set = {}
|
|
82
|
+
hash.each_key do |key|
|
|
83
|
+
key = coerce_key(key, as_json)
|
|
84
|
+
if set[key]
|
|
85
|
+
raise GeneratorError.new("detected duplicate key #{key.inspect}", key)
|
|
86
|
+
else
|
|
87
|
+
set[key] = true
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
31
93
|
require 'json/ext/parser'
|
|
32
94
|
Ext::Parser::Config = Ext::ParserConfig
|
|
33
95
|
JSON.parser = Ext::Parser
|
|
34
96
|
|
|
35
|
-
if RUBY_ENGINE == 'truffleruby'
|
|
97
|
+
generator = if RUBY_ENGINE == 'truffleruby'
|
|
36
98
|
require 'json/truffle_ruby/generator'
|
|
37
|
-
JSON
|
|
99
|
+
JSON::TruffleRuby::Generator
|
|
38
100
|
else
|
|
39
101
|
require 'json/ext/generator'
|
|
40
|
-
|
|
102
|
+
Generator
|
|
41
103
|
end
|
|
104
|
+
|
|
105
|
+
# The default proc used when the +sort_keys+ generation option is +true+.
|
|
106
|
+
# It returns a new hash with the entries sorted by their keys.
|
|
107
|
+
generator::State.default_sort_keys_proc = shareable_lambda(->(hash) {
|
|
108
|
+
hash.sort.to_h
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
# Directly lifted from Gregg Kellogg's json-canonicalization
|
|
112
|
+
generator::State.rfc8785_number_formatter_proc = shareable_lambda(->(num) {
|
|
113
|
+
if Integer === num
|
|
114
|
+
if num > Float::MAX || num < -Float::MAX
|
|
115
|
+
raise GeneratorError.new("Integer out of range for RFC 8785", num)
|
|
116
|
+
end
|
|
117
|
+
num = num.to_f
|
|
118
|
+
end
|
|
119
|
+
if num.zero?
|
|
120
|
+
"0"
|
|
121
|
+
else
|
|
122
|
+
if num < 0
|
|
123
|
+
num, sign = -num, '-'
|
|
124
|
+
end
|
|
125
|
+
native_rep = num.to_s
|
|
126
|
+
decimal, exponential = native_rep.split('e')
|
|
127
|
+
exp_val = exponential.to_i
|
|
128
|
+
exponential = exp_val > 0 ? ('+' + exp_val.to_s) : exp_val.to_s
|
|
129
|
+
|
|
130
|
+
integral, fractional = decimal.split('.')
|
|
131
|
+
fractional = fractional.sub(/0+$/, '') # Remove trailing zeros
|
|
132
|
+
|
|
133
|
+
if exp_val > 0 && exp_val < 21
|
|
134
|
+
while exp_val > 0
|
|
135
|
+
integral += fractional.to_s[0] || '0'
|
|
136
|
+
fractional = fractional.to_s[1..-1]
|
|
137
|
+
exp_val -= 1
|
|
138
|
+
end
|
|
139
|
+
exponential = nil
|
|
140
|
+
elsif exp_val == 0
|
|
141
|
+
exponential = nil
|
|
142
|
+
elsif exp_val < 0 && exp_val > -7
|
|
143
|
+
# Small numbers are shown as 0.etc with e-6 as lower limit
|
|
144
|
+
fractional, integral, exponential = integral + fractional.to_s, '0', nil
|
|
145
|
+
fractional = ("0" * (-exp_val - 1)) + fractional
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
fractional = nil if fractional.to_s.empty?
|
|
149
|
+
sign.to_s + integral + (fractional ? ".#{fractional}" : '') + (exponential ? "e#{exponential}" : '')
|
|
150
|
+
end
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
generator::State.rfc8785_sort_keys_proc = shareable_lambda(->(hash, as_json) {
|
|
154
|
+
converted = if as_json
|
|
155
|
+
hash.transform_keys { |k| Ext.coerce_key(k, as_json) }
|
|
156
|
+
else
|
|
157
|
+
hash.transform_keys(&:to_s)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if converted.size < hash.size
|
|
161
|
+
Ext.on_duplicate_key(hash, as_json)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
converted.sort_by { |k,| k.encode(Encoding::UTF_16) }.to_h
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
JSON.generator = generator
|
|
42
168
|
end
|
|
43
169
|
|
|
44
170
|
if defined?(ResumableParser) # Not yet available on JRuby
|
|
@@ -66,6 +192,4 @@ module JSON
|
|
|
66
192
|
end
|
|
67
193
|
end
|
|
68
194
|
end
|
|
69
|
-
|
|
70
|
-
JSON_LOADED = true unless defined?(JSON::JSON_LOADED)
|
|
71
195
|
end
|
|
@@ -112,6 +112,8 @@ module JSON
|
|
|
112
112
|
# while generating a JSON text from a Ruby data structure.
|
|
113
113
|
class State
|
|
114
114
|
singleton_class.attr_accessor :default_sort_keys_proc # :nodoc:
|
|
115
|
+
singleton_class.attr_accessor :rfc8785_number_formatter_proc # :nodoc:
|
|
116
|
+
singleton_class.attr_accessor :rfc8785_sort_keys_proc # :nodoc:
|
|
115
117
|
|
|
116
118
|
def self.generate(obj, opts = nil, io = nil)
|
|
117
119
|
new(opts).generate(obj, io)
|
|
@@ -125,7 +127,7 @@ module JSON
|
|
|
125
127
|
if opts
|
|
126
128
|
case
|
|
127
129
|
when self === opts
|
|
128
|
-
return opts
|
|
130
|
+
return opts.validate_rfc8785
|
|
129
131
|
when opts.respond_to?(:to_hash)
|
|
130
132
|
return new(opts.to_hash)
|
|
131
133
|
when opts.respond_to?(:to_h)
|
|
@@ -167,7 +169,9 @@ module JSON
|
|
|
167
169
|
@strict = false
|
|
168
170
|
@max_nesting = 100
|
|
169
171
|
@sort_keys = false
|
|
170
|
-
|
|
172
|
+
@allow_duplicate_key = false
|
|
173
|
+
@rfc8785 = false
|
|
174
|
+
_configure(**opts) if opts
|
|
171
175
|
end
|
|
172
176
|
|
|
173
177
|
# This string is used to indent levels in the JSON text.
|
|
@@ -188,7 +192,16 @@ module JSON
|
|
|
188
192
|
attr_accessor :array_nl
|
|
189
193
|
|
|
190
194
|
# This proc converts unsupported types into native JSON types.
|
|
191
|
-
|
|
195
|
+
attr_reader :as_json
|
|
196
|
+
|
|
197
|
+
def as_json=(value)
|
|
198
|
+
raise FrozenError, "can't modify frozen #{self.class}: #{inspect}" if frozen?
|
|
199
|
+
value = value.to_proc if !(Proc === value) && value.respond_to?(:to_proc)
|
|
200
|
+
unless Proc === value
|
|
201
|
+
raise TypeError, "as_json must be a Proc"
|
|
202
|
+
end
|
|
203
|
+
@as_json = value
|
|
204
|
+
end
|
|
192
205
|
|
|
193
206
|
# This integer returns the maximum level of data structure nesting in
|
|
194
207
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
|
@@ -208,6 +221,9 @@ module JSON
|
|
|
208
221
|
# desired order.
|
|
209
222
|
attr_reader :sort_keys
|
|
210
223
|
|
|
224
|
+
# Controls whether RFC8785 (canonicalization) mode is enabled. Otherwise returns false.
|
|
225
|
+
attr_writer :rfc8785
|
|
226
|
+
|
|
211
227
|
def sort_keys=(value) # :nodoc:
|
|
212
228
|
type_error = false
|
|
213
229
|
@sort_keys = case value
|
|
@@ -287,67 +303,80 @@ module JSON
|
|
|
287
303
|
@strict
|
|
288
304
|
end
|
|
289
305
|
|
|
290
|
-
#
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
opts = opts.to_hash
|
|
295
|
-
elsif opts.respond_to?(:to_h)
|
|
296
|
-
opts = opts.to_h
|
|
297
|
-
else
|
|
298
|
-
raise TypeError, "can't convert #{opts.class} into Hash"
|
|
299
|
-
end
|
|
306
|
+
# Returns true, if RFC8785 (canonicalization) mode is enabled. Otherwise returns false.
|
|
307
|
+
def rfc8785?
|
|
308
|
+
@rfc8785
|
|
309
|
+
end
|
|
300
310
|
|
|
301
|
-
|
|
302
|
-
|
|
311
|
+
def validate_rfc8785 # :nodoc:
|
|
312
|
+
if @rfc8785
|
|
313
|
+
option = if !@indent.empty? then :indent
|
|
314
|
+
elsif !@space.empty? then :space
|
|
315
|
+
elsif !@space_before.empty? then :space_before
|
|
316
|
+
elsif !@object_nl.empty? then :object_nl
|
|
317
|
+
elsif !@array_nl.empty? then :array_nl
|
|
318
|
+
elsif @ascii_only then :ascii_only
|
|
319
|
+
elsif @script_safe then :script_safe
|
|
320
|
+
elsif @allow_nan then :allow_nan
|
|
321
|
+
end
|
|
322
|
+
raise ArgumentError, "#{option} cannot be used with rfc8785" if option
|
|
303
323
|
end
|
|
324
|
+
self
|
|
325
|
+
end
|
|
304
326
|
|
|
305
|
-
|
|
306
|
-
|
|
327
|
+
# Configure this State instance with the Hash _opts_, and return
|
|
328
|
+
# itself.
|
|
329
|
+
def configure(options)
|
|
330
|
+
unless Hash == options
|
|
331
|
+
if options.respond_to?(:to_hash)
|
|
332
|
+
options = options.to_hash
|
|
333
|
+
elsif options.respond_to?(:to_h)
|
|
334
|
+
options = options.to_h
|
|
335
|
+
end
|
|
307
336
|
end
|
|
337
|
+
_configure(**options)
|
|
338
|
+
end
|
|
339
|
+
alias merge configure
|
|
308
340
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
@space
|
|
312
|
-
@
|
|
313
|
-
@
|
|
314
|
-
@
|
|
315
|
-
@
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
@depth = opts[:depth] || 0
|
|
320
|
-
@buffer_initial_length ||= opts[:buffer_initial_length]
|
|
321
|
-
|
|
322
|
-
@script_safe = if opts.key?(:script_safe)
|
|
323
|
-
!!opts[:script_safe]
|
|
324
|
-
elsif opts.key?(:escape_slash)
|
|
325
|
-
!!opts[:escape_slash]
|
|
326
|
-
else
|
|
327
|
-
false
|
|
341
|
+
# Defaults are the current values so that #configure only writes what it was given.
|
|
342
|
+
private def _configure(
|
|
343
|
+
indent: @indent, space: @space, space_before: @space_before, object_nl: @object_nl,
|
|
344
|
+
array_nl: @array_nl, allow_nan: @allow_nan, as_json: @as_json, ascii_only: @ascii_only,
|
|
345
|
+
sort_keys: @sort_keys, depth: @depth, buffer_initial_length: @buffer_initial_length,
|
|
346
|
+
allow_duplicate_key: @allow_duplicate_key, script_safe: @script_safe, strict: @strict,
|
|
347
|
+
max_nesting: @max_nesting, rfc8785: @rfc8785
|
|
348
|
+
)
|
|
349
|
+
if depth.negative?
|
|
350
|
+
raise ArgumentError, "depth must be >= 0 (got #{depth})"
|
|
328
351
|
end
|
|
329
352
|
|
|
330
|
-
if
|
|
331
|
-
|
|
332
|
-
else
|
|
333
|
-
@allow_duplicate_key = nil # nil is deprecation
|
|
353
|
+
if max_nesting && !(Integer === max_nesting)
|
|
354
|
+
raise TypeError, ":max_nesting must be `false` or an Integer, got: #{max_nesting.class}"
|
|
334
355
|
end
|
|
335
356
|
|
|
336
|
-
@
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
@max_nesting = opts[:max_nesting]
|
|
357
|
+
@indent = indent || ''
|
|
358
|
+
@space = space || ''
|
|
359
|
+
@space_before = space_before || ''
|
|
360
|
+
@object_nl = object_nl || ''
|
|
361
|
+
@array_nl = array_nl || ''
|
|
362
|
+
@allow_nan = allow_nan || false
|
|
363
|
+
if as_json
|
|
364
|
+
self.as_json = as_json
|
|
345
365
|
else
|
|
346
|
-
@
|
|
366
|
+
@as_json = false
|
|
347
367
|
end
|
|
348
|
-
|
|
368
|
+
@ascii_only = ascii_only || false
|
|
369
|
+
self.sort_keys = sort_keys
|
|
370
|
+
@depth = depth
|
|
371
|
+
@buffer_initial_length = buffer_initial_length
|
|
372
|
+
@allow_duplicate_key = allow_duplicate_key
|
|
373
|
+
@script_safe = script_safe
|
|
374
|
+
@strict = strict
|
|
375
|
+
@max_nesting = max_nesting || 0
|
|
376
|
+
self.rfc8785 = rfc8785
|
|
377
|
+
|
|
378
|
+
validate_rfc8785
|
|
349
379
|
end
|
|
350
|
-
alias merge configure
|
|
351
380
|
|
|
352
381
|
def allow_duplicate_key? # :nodoc:
|
|
353
382
|
@allow_duplicate_key
|
|
@@ -356,17 +385,24 @@ module JSON
|
|
|
356
385
|
# Returns the configuration instance variables as a hash, that can be
|
|
357
386
|
# passed to the configure method.
|
|
358
387
|
def to_h
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
388
|
+
{
|
|
389
|
+
indent: @indent,
|
|
390
|
+
space: @space,
|
|
391
|
+
space_before: @space_before,
|
|
392
|
+
object_nl: @object_nl,
|
|
393
|
+
array_nl: @array_nl,
|
|
394
|
+
as_json: @as_json,
|
|
395
|
+
allow_nan: @allow_nan,
|
|
396
|
+
ascii_only: @ascii_only,
|
|
397
|
+
max_nesting: @max_nesting,
|
|
398
|
+
script_safe: @script_safe,
|
|
399
|
+
strict: @strict,
|
|
400
|
+
depth: @depth,
|
|
401
|
+
buffer_initial_length: @buffer_initial_length,
|
|
402
|
+
sort_keys: @sort_keys,
|
|
403
|
+
allow_duplicate_key: @allow_duplicate_key,
|
|
404
|
+
rfc8785: @rfc8785,
|
|
405
|
+
}
|
|
370
406
|
end
|
|
371
407
|
|
|
372
408
|
alias to_hash to_h
|
|
@@ -379,16 +415,14 @@ module JSON
|
|
|
379
415
|
return dup.generate(obj, anIO) if frozen?
|
|
380
416
|
|
|
381
417
|
depth = @depth
|
|
418
|
+
validate_rfc8785
|
|
382
419
|
if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and
|
|
383
420
|
!@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj) and !@sort_keys
|
|
384
421
|
result = generate_json(obj, ''.dup)
|
|
385
422
|
else
|
|
386
|
-
if @sort_keys
|
|
387
|
-
obj = @sort_keys.call(obj)
|
|
388
|
-
end
|
|
389
|
-
|
|
390
423
|
result = obj.to_json(self)
|
|
391
424
|
end
|
|
425
|
+
|
|
392
426
|
JSON::TruffleRuby::Generator.valid_utf8?(result) or raise GeneratorError.new(
|
|
393
427
|
"source sequence #{result.inspect} is illegal/malformed utf-8",
|
|
394
428
|
obj
|
|
@@ -410,13 +444,18 @@ module JSON
|
|
|
410
444
|
buf << '{'
|
|
411
445
|
first = true
|
|
412
446
|
key_type = nil
|
|
447
|
+
if @rfc8785
|
|
448
|
+
obj = State.rfc8785_sort_keys_proc.call(obj, @strict && @as_json)
|
|
449
|
+
elsif @sort_keys
|
|
450
|
+
obj = @sort_keys.call(obj)
|
|
451
|
+
end
|
|
413
452
|
obj.each_pair do |k,v|
|
|
414
453
|
if first
|
|
415
454
|
key_type = k.class
|
|
416
455
|
else
|
|
417
456
|
if key_type && !@allow_duplicate_key && key_type != k.class
|
|
418
457
|
key_type = nil # stop checking
|
|
419
|
-
JSON.send(:on_mixed_keys_hash, obj
|
|
458
|
+
JSON.send(:on_mixed_keys_hash, obj)
|
|
420
459
|
end
|
|
421
460
|
buf << ','
|
|
422
461
|
end
|
|
@@ -451,7 +490,7 @@ module JSON
|
|
|
451
490
|
buf << obj.to_json(self)
|
|
452
491
|
end
|
|
453
492
|
when Integer
|
|
454
|
-
buf << obj.to_s
|
|
493
|
+
buf << (@rfc8785 ? State.rfc8785_number_formatter_proc.call(obj) : obj.to_s)
|
|
455
494
|
when Symbol
|
|
456
495
|
if @strict
|
|
457
496
|
fast_serialize_string(obj.name, buf)
|
|
@@ -483,28 +522,6 @@ module JSON
|
|
|
483
522
|
end
|
|
484
523
|
buf << '"'
|
|
485
524
|
end
|
|
486
|
-
|
|
487
|
-
# Return the value returned by method +name+.
|
|
488
|
-
def [](name)
|
|
489
|
-
::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
|
|
490
|
-
|
|
491
|
-
if respond_to?(name)
|
|
492
|
-
__send__(name)
|
|
493
|
-
else
|
|
494
|
-
instance_variable_get("@#{name}") if
|
|
495
|
-
instance_variables.include?("@#{name}".to_sym) # avoid warning
|
|
496
|
-
end
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
def []=(name, value)
|
|
500
|
-
::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
|
|
501
|
-
|
|
502
|
-
if respond_to?(name_writer = "#{name}=")
|
|
503
|
-
__send__ name_writer, value
|
|
504
|
-
else
|
|
505
|
-
instance_variable_set "@#{name}", value
|
|
506
|
-
end
|
|
507
|
-
end
|
|
508
525
|
end
|
|
509
526
|
|
|
510
527
|
module GeneratorMethods
|
|
@@ -542,10 +559,12 @@ module JSON
|
|
|
542
559
|
def to_json(state = nil, *)
|
|
543
560
|
state = State.from_state(state)
|
|
544
561
|
depth = state.depth
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
562
|
+
begin
|
|
563
|
+
state.check_max_nesting
|
|
564
|
+
json_transform(state)
|
|
565
|
+
ensure
|
|
566
|
+
state.depth = depth
|
|
567
|
+
end
|
|
549
568
|
end
|
|
550
569
|
|
|
551
570
|
private
|
|
@@ -563,13 +582,21 @@ module JSON
|
|
|
563
582
|
first = true
|
|
564
583
|
key_type = nil
|
|
565
584
|
indent = !state.object_nl.empty?
|
|
566
|
-
|
|
585
|
+
hash = self
|
|
586
|
+
|
|
587
|
+
if state.rfc8785?
|
|
588
|
+
hash = State.rfc8785_sort_keys_proc.call(hash, state.strict? && state.as_json)
|
|
589
|
+
elsif state.sort_keys
|
|
590
|
+
hash = state.sort_keys.call(hash)
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
hash.each { |key, value|
|
|
567
594
|
if first
|
|
568
595
|
key_type = key.class
|
|
569
596
|
else
|
|
570
597
|
if key_type && !state.allow_duplicate_key? && key_type != key.class
|
|
571
598
|
key_type = nil # stop checking
|
|
572
|
-
JSON.send(:on_mixed_keys_hash,
|
|
599
|
+
JSON.send(:on_mixed_keys_hash, hash)
|
|
573
600
|
end
|
|
574
601
|
result << delim
|
|
575
602
|
end
|
|
@@ -634,10 +661,12 @@ module JSON
|
|
|
634
661
|
def to_json(state = nil, *)
|
|
635
662
|
state = State.from_state(state)
|
|
636
663
|
depth = state.depth
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
664
|
+
begin
|
|
665
|
+
state.check_max_nesting
|
|
666
|
+
json_transform(state)
|
|
667
|
+
ensure
|
|
668
|
+
state.depth = depth
|
|
669
|
+
end
|
|
641
670
|
end
|
|
642
671
|
|
|
643
672
|
private
|
|
@@ -690,13 +719,20 @@ module JSON
|
|
|
690
719
|
|
|
691
720
|
module Integer
|
|
692
721
|
# Returns a JSON string representation for this Integer number.
|
|
693
|
-
def to_json(*)
|
|
722
|
+
def to_json(state = nil, *)
|
|
723
|
+
if state && State.from_state(state).rfc8785?
|
|
724
|
+
State.rfc8785_number_formatter_proc.call(self)
|
|
725
|
+
else
|
|
726
|
+
to_s
|
|
727
|
+
end
|
|
728
|
+
end
|
|
694
729
|
end
|
|
695
730
|
|
|
696
731
|
module Float
|
|
697
732
|
# Returns a JSON string representation for this Float number.
|
|
698
733
|
def to_json(state = nil, *args)
|
|
699
734
|
state = State.from_state(state)
|
|
735
|
+
|
|
700
736
|
if infinite? || nan?
|
|
701
737
|
if state.allow_nan?
|
|
702
738
|
to_s
|
|
@@ -718,6 +754,8 @@ module JSON
|
|
|
718
754
|
else
|
|
719
755
|
raise GeneratorError.new("#{self} not allowed in JSON", self)
|
|
720
756
|
end
|
|
757
|
+
elsif state.rfc8785?
|
|
758
|
+
State.rfc8785_number_formatter_proc.call(self)
|
|
721
759
|
else
|
|
722
760
|
to_s
|
|
723
761
|
end
|
data/lib/json/version.rb
CHANGED