json 2.7.2 → 2.10.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.
- checksums.yaml +4 -4
- data/BSDL +22 -0
- data/CHANGES.md +98 -17
- data/LEGAL +8 -0
- data/README.md +68 -216
- data/ext/json/ext/fbuffer/fbuffer.h +110 -92
- data/ext/json/ext/generator/extconf.rb +8 -2
- data/ext/json/ext/generator/generator.c +952 -833
- data/ext/json/ext/parser/extconf.rb +7 -27
- data/ext/json/ext/parser/parser.c +1207 -1940
- data/json.gemspec +44 -49
- data/lib/json/add/bigdecimal.rb +2 -2
- data/lib/json/add/complex.rb +1 -1
- data/lib/json/add/core.rb +1 -1
- data/lib/json/add/date.rb +1 -1
- data/lib/json/add/date_time.rb +1 -1
- data/lib/json/add/exception.rb +1 -1
- data/lib/json/add/ostruct.rb +1 -1
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +1 -1
- data/lib/json/add/regexp.rb +1 -1
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +8 -4
- data/lib/json/add/time.rb +3 -10
- data/lib/json/common.rb +401 -106
- data/lib/json/ext/generator/state.rb +106 -0
- data/lib/json/ext.rb +34 -4
- data/lib/json/generic_object.rb +1 -1
- data/lib/json/{pure → truffle_ruby}/generator.rb +322 -145
- data/lib/json/version.rb +3 -7
- data/lib/json.rb +16 -21
- metadata +15 -22
- data/ext/json/ext/generator/depend +0 -1
- data/ext/json/ext/generator/generator.h +0 -177
- data/ext/json/ext/parser/depend +0 -1
- data/ext/json/ext/parser/parser.h +0 -96
- data/ext/json/ext/parser/parser.rl +0 -971
- data/ext/json/extconf.rb +0 -3
- data/lib/json/pure/parser.rb +0 -337
- data/lib/json/pure.rb +0 -15
- /data/{LICENSE → COPYING} +0 -0
@@ -1,118 +1,123 @@
|
|
1
|
-
#frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module JSON
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
3
|
+
module TruffleRuby
|
4
|
+
module Generator
|
5
|
+
MAP = {
|
6
|
+
"\x0" => '\u0000',
|
7
|
+
"\x1" => '\u0001',
|
8
|
+
"\x2" => '\u0002',
|
9
|
+
"\x3" => '\u0003',
|
10
|
+
"\x4" => '\u0004',
|
11
|
+
"\x5" => '\u0005',
|
12
|
+
"\x6" => '\u0006',
|
13
|
+
"\x7" => '\u0007',
|
14
|
+
"\b" => '\b',
|
15
|
+
"\t" => '\t',
|
16
|
+
"\n" => '\n',
|
17
|
+
"\xb" => '\u000b',
|
18
|
+
"\f" => '\f',
|
19
|
+
"\r" => '\r',
|
20
|
+
"\xe" => '\u000e',
|
21
|
+
"\xf" => '\u000f',
|
22
|
+
"\x10" => '\u0010',
|
23
|
+
"\x11" => '\u0011',
|
24
|
+
"\x12" => '\u0012',
|
25
|
+
"\x13" => '\u0013',
|
26
|
+
"\x14" => '\u0014',
|
27
|
+
"\x15" => '\u0015',
|
28
|
+
"\x16" => '\u0016',
|
29
|
+
"\x17" => '\u0017',
|
30
|
+
"\x18" => '\u0018',
|
31
|
+
"\x19" => '\u0019',
|
32
|
+
"\x1a" => '\u001a',
|
33
|
+
"\x1b" => '\u001b',
|
34
|
+
"\x1c" => '\u001c',
|
35
|
+
"\x1d" => '\u001d',
|
36
|
+
"\x1e" => '\u001e',
|
37
|
+
"\x1f" => '\u001f',
|
38
|
+
'"' => '\"',
|
39
|
+
'\\' => '\\\\',
|
40
|
+
}.freeze # :nodoc:
|
41
|
+
|
42
|
+
SCRIPT_SAFE_MAP = MAP.merge(
|
43
|
+
'/' => '\\/',
|
44
|
+
"\u2028" => '\u2028',
|
45
|
+
"\u2029" => '\u2029',
|
46
|
+
).freeze
|
47
|
+
|
48
|
+
SCRIPT_SAFE_ESCAPE_PATTERN = /[\/"\\\x0-\x1f\u2028-\u2029]/
|
49
|
+
|
50
|
+
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
|
51
|
+
# UTF16 big endian characters as \u????, and return it.
|
52
|
+
def self.utf8_to_json(string, script_safe = false) # :nodoc:
|
53
|
+
if script_safe
|
54
|
+
if SCRIPT_SAFE_ESCAPE_PATTERN.match?(string)
|
55
|
+
string.gsub(SCRIPT_SAFE_ESCAPE_PATTERN, SCRIPT_SAFE_MAP)
|
56
|
+
else
|
57
|
+
string
|
58
|
+
end
|
59
|
+
else
|
60
|
+
if /["\\\x0-\x1f]/.match?(string)
|
61
|
+
string.gsub(/["\\\x0-\x1f]/, MAP)
|
62
|
+
else
|
63
|
+
string
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
63
67
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
68
|
+
def self.utf8_to_json_ascii(original_string, script_safe = false) # :nodoc:
|
69
|
+
string = original_string.b
|
70
|
+
map = script_safe ? SCRIPT_SAFE_MAP : MAP
|
71
|
+
string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
|
72
|
+
string.gsub!(/(
|
73
|
+
(?:
|
74
|
+
[\xc2-\xdf][\x80-\xbf] |
|
75
|
+
[\xe0-\xef][\x80-\xbf]{2} |
|
76
|
+
[\xf0-\xf4][\x80-\xbf]{3}
|
77
|
+
)+ |
|
78
|
+
[\x80-\xc1\xf5-\xff] # invalid
|
79
|
+
)/nx) { |c|
|
80
|
+
c.size == 1 and raise GeneratorError.new("invalid utf8 byte: '#{c}'", original_string)
|
81
|
+
s = c.encode(::Encoding::UTF_16BE, ::Encoding::UTF_8).unpack('H*')[0]
|
82
|
+
s.force_encoding(::Encoding::BINARY)
|
83
|
+
s.gsub!(/.{4}/n, '\\\\u\&')
|
84
|
+
s.force_encoding(::Encoding::UTF_8)
|
85
|
+
}
|
86
|
+
string.force_encoding(::Encoding::UTF_8)
|
87
|
+
string
|
88
|
+
rescue => e
|
89
|
+
raise GeneratorError.new(e.message, original_string)
|
90
|
+
end
|
88
91
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
|
92
|
+
def self.valid_utf8?(string)
|
93
|
+
encoding = string.encoding
|
94
|
+
(encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
|
95
|
+
string.valid_encoding?
|
96
|
+
end
|
95
97
|
|
96
|
-
module Pure
|
97
|
-
module Generator
|
98
98
|
# This class is used to create State instances, that are use to hold data
|
99
99
|
# while generating a JSON text from a Ruby data structure.
|
100
100
|
class State
|
101
|
+
def self.generate(obj, opts = nil, io = nil)
|
102
|
+
new(opts).generate(obj, io)
|
103
|
+
end
|
104
|
+
|
101
105
|
# Creates a State object from _opts_, which ought to be Hash to create
|
102
106
|
# a new State instance configured by _opts_, something else to create
|
103
107
|
# an unconfigured instance. If _opts_ is a State object, it is just
|
104
108
|
# returned.
|
105
109
|
def self.from_state(opts)
|
106
|
-
|
107
|
-
|
108
|
-
opts
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
if opts
|
111
|
+
case
|
112
|
+
when self === opts
|
113
|
+
return opts
|
114
|
+
when opts.respond_to?(:to_hash)
|
115
|
+
return new(opts.to_hash)
|
116
|
+
when opts.respond_to?(:to_h)
|
117
|
+
return new(opts.to_h)
|
118
|
+
end
|
115
119
|
end
|
120
|
+
SAFE_STATE_PROTOTYPE.dup
|
116
121
|
end
|
117
122
|
|
118
123
|
# Instantiates a new State object, configured by _opts_.
|
@@ -132,7 +137,7 @@ module JSON
|
|
132
137
|
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
133
138
|
# generated, otherwise an exception is thrown, if these values are
|
134
139
|
# encountered. This options defaults to false.
|
135
|
-
def initialize(opts =
|
140
|
+
def initialize(opts = nil)
|
136
141
|
@indent = ''
|
137
142
|
@space = ''
|
138
143
|
@space_before = ''
|
@@ -140,10 +145,13 @@ module JSON
|
|
140
145
|
@array_nl = ''
|
141
146
|
@allow_nan = false
|
142
147
|
@ascii_only = false
|
143
|
-
@
|
144
|
-
@
|
148
|
+
@as_json = false
|
149
|
+
@depth = 0
|
145
150
|
@buffer_initial_length = 1024
|
146
|
-
|
151
|
+
@script_safe = false
|
152
|
+
@strict = false
|
153
|
+
@max_nesting = 100
|
154
|
+
configure(opts) if opts
|
147
155
|
end
|
148
156
|
|
149
157
|
# This string is used to indent levels in the JSON text.
|
@@ -163,6 +171,9 @@ module JSON
|
|
163
171
|
# This string is put at the end of a line that holds a JSON array.
|
164
172
|
attr_accessor :array_nl
|
165
173
|
|
174
|
+
# This proc converts unsupported types into native JSON types.
|
175
|
+
attr_accessor :as_json
|
176
|
+
|
166
177
|
# This integer returns the maximum level of data structure nesting in
|
167
178
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
168
179
|
attr_accessor :max_nesting
|
@@ -219,7 +230,9 @@ module JSON
|
|
219
230
|
@script_safe
|
220
231
|
end
|
221
232
|
|
222
|
-
# Returns true, if
|
233
|
+
# Returns true, if strict mode is enabled. Otherwise returns false.
|
234
|
+
# Strict mode only allow serializing JSON native types: Hash, Array,
|
235
|
+
# String, Integer, Float, true, false and nil.
|
223
236
|
def strict?
|
224
237
|
@strict
|
225
238
|
end
|
@@ -237,13 +250,16 @@ module JSON
|
|
237
250
|
opts.each do |key, value|
|
238
251
|
instance_variable_set "@#{key}", value
|
239
252
|
end
|
240
|
-
|
241
|
-
|
242
|
-
@
|
243
|
-
@
|
244
|
-
@
|
245
|
-
@
|
246
|
-
@
|
253
|
+
|
254
|
+
# NOTE: If adding new instance variables here, check whether #generate should check them for #generate_json
|
255
|
+
@indent = opts[:indent] || '' if opts.key?(:indent)
|
256
|
+
@space = opts[:space] || '' if opts.key?(:space)
|
257
|
+
@space_before = opts[:space_before] || '' if opts.key?(:space_before)
|
258
|
+
@object_nl = opts[:object_nl] || '' if opts.key?(:object_nl)
|
259
|
+
@array_nl = opts[:array_nl] || '' if opts.key?(:array_nl)
|
260
|
+
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
261
|
+
@as_json = opts[:as_json].to_proc if opts[:as_json]
|
262
|
+
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
247
263
|
@depth = opts[:depth] || 0
|
248
264
|
@buffer_initial_length ||= opts[:buffer_initial_length]
|
249
265
|
|
@@ -285,11 +301,99 @@ module JSON
|
|
285
301
|
# returns the result. If no valid JSON document can be
|
286
302
|
# created this method raises a
|
287
303
|
# GeneratorError exception.
|
288
|
-
def generate(obj)
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
304
|
+
def generate(obj, anIO = nil)
|
305
|
+
if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and
|
306
|
+
!@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj)
|
307
|
+
result = generate_json(obj, ''.dup)
|
308
|
+
else
|
309
|
+
result = obj.to_json(self)
|
310
|
+
end
|
311
|
+
JSON::TruffleRuby::Generator.valid_utf8?(result) or raise GeneratorError.new(
|
312
|
+
"source sequence #{result.inspect} is illegal/malformed utf-8",
|
313
|
+
obj
|
314
|
+
)
|
315
|
+
if anIO
|
316
|
+
anIO.write(result)
|
317
|
+
anIO
|
318
|
+
else
|
319
|
+
result
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def generate_new(obj, anIO = nil) # :nodoc:
|
324
|
+
dup.generate(obj, anIO)
|
325
|
+
end
|
326
|
+
|
327
|
+
# Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
|
328
|
+
private def generate_json(obj, buf)
|
329
|
+
case obj
|
330
|
+
when Hash
|
331
|
+
buf << '{'
|
332
|
+
first = true
|
333
|
+
obj.each_pair do |k,v|
|
334
|
+
buf << ',' unless first
|
335
|
+
|
336
|
+
key_str = k.to_s
|
337
|
+
if key_str.class == String
|
338
|
+
fast_serialize_string(key_str, buf)
|
339
|
+
elsif key_str.is_a?(String)
|
340
|
+
generate_json(key_str, buf)
|
341
|
+
else
|
342
|
+
raise TypeError, "#{k.class}#to_s returns an instance of #{key_str.class}, expected a String"
|
343
|
+
end
|
344
|
+
|
345
|
+
buf << ':'
|
346
|
+
generate_json(v, buf)
|
347
|
+
first = false
|
348
|
+
end
|
349
|
+
buf << '}'
|
350
|
+
when Array
|
351
|
+
buf << '['
|
352
|
+
first = true
|
353
|
+
obj.each do |e|
|
354
|
+
buf << ',' unless first
|
355
|
+
generate_json(e, buf)
|
356
|
+
first = false
|
357
|
+
end
|
358
|
+
buf << ']'
|
359
|
+
when String
|
360
|
+
if obj.class == String
|
361
|
+
fast_serialize_string(obj, buf)
|
362
|
+
else
|
363
|
+
buf << obj.to_json(self)
|
364
|
+
end
|
365
|
+
when Integer
|
366
|
+
buf << obj.to_s
|
367
|
+
when Symbol
|
368
|
+
if @strict
|
369
|
+
fast_serialize_string(obj.name, buf)
|
370
|
+
else
|
371
|
+
buf << obj.to_json(self)
|
372
|
+
end
|
373
|
+
else
|
374
|
+
# Note: Float is handled this way since Float#to_s is slow anyway
|
375
|
+
buf << obj.to_json(self)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
# Assumes !@ascii_only, !@script_safe
|
380
|
+
private def fast_serialize_string(string, buf) # :nodoc:
|
381
|
+
buf << '"'
|
382
|
+
unless string.encoding == ::Encoding::UTF_8
|
383
|
+
begin
|
384
|
+
string = string.encode(::Encoding::UTF_8)
|
385
|
+
rescue Encoding::UndefinedConversionError => error
|
386
|
+
raise GeneratorError.new(error.message, string)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
raise GeneratorError.new("source sequence is illegal/malformed utf-8", string) unless string.valid_encoding?
|
390
|
+
|
391
|
+
if /["\\\x0-\x1f]/.match?(string)
|
392
|
+
buf << string.gsub(/["\\\x0-\x1f]/, MAP)
|
393
|
+
else
|
394
|
+
buf << string
|
395
|
+
end
|
396
|
+
buf << '"'
|
293
397
|
end
|
294
398
|
|
295
399
|
# Return the value returned by method +name+.
|
@@ -316,9 +420,21 @@ module JSON
|
|
316
420
|
# Converts this object to a string (calling #to_s), converts
|
317
421
|
# it to a JSON string, and returns the result. This is a fallback, if no
|
318
422
|
# special method #to_json was defined for some object.
|
319
|
-
def to_json(
|
320
|
-
if
|
321
|
-
|
423
|
+
def to_json(state = nil, *)
|
424
|
+
state = State.from_state(state) if state
|
425
|
+
if state&.strict?
|
426
|
+
value = self
|
427
|
+
if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
|
428
|
+
if state.as_json
|
429
|
+
value = state.as_json.call(value)
|
430
|
+
unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value
|
431
|
+
raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
|
432
|
+
end
|
433
|
+
value.to_json(state)
|
434
|
+
else
|
435
|
+
raise GeneratorError.new("#{value.class} not allowed in JSON", value)
|
436
|
+
end
|
437
|
+
end
|
322
438
|
else
|
323
439
|
to_s.to_json
|
324
440
|
end
|
@@ -345,17 +461,39 @@ module JSON
|
|
345
461
|
end
|
346
462
|
|
347
463
|
def json_transform(state)
|
348
|
-
delim = ",#{state.object_nl}"
|
349
|
-
result = "{#{state.object_nl}"
|
350
464
|
depth = state.depth += 1
|
465
|
+
|
466
|
+
if empty?
|
467
|
+
state.depth -= 1
|
468
|
+
return '{}'
|
469
|
+
end
|
470
|
+
|
471
|
+
delim = ",#{state.object_nl}"
|
472
|
+
result = +"{#{state.object_nl}"
|
351
473
|
first = true
|
352
474
|
indent = !state.object_nl.empty?
|
353
475
|
each { |key, value|
|
354
476
|
result << delim unless first
|
355
477
|
result << state.indent * depth if indent
|
356
|
-
|
357
|
-
|
358
|
-
|
478
|
+
|
479
|
+
key_str = key.to_s
|
480
|
+
if key_str.is_a?(String)
|
481
|
+
key_json = key_str.to_json(state)
|
482
|
+
else
|
483
|
+
raise TypeError, "#{key.class}#to_s returns an instance of #{key_str.class}, expected a String"
|
484
|
+
end
|
485
|
+
|
486
|
+
result = +"#{result}#{key_json}#{state.space_before}:#{state.space}"
|
487
|
+
if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
|
488
|
+
if state.as_json
|
489
|
+
value = state.as_json.call(value)
|
490
|
+
unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value
|
491
|
+
raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
|
492
|
+
end
|
493
|
+
result << value.to_json(state)
|
494
|
+
else
|
495
|
+
raise GeneratorError.new("#{value.class} not allowed in JSON", value)
|
496
|
+
end
|
359
497
|
elsif value.respond_to?(:to_json)
|
360
498
|
result << value.to_json(state)
|
361
499
|
else
|
@@ -387,18 +525,36 @@ module JSON
|
|
387
525
|
private
|
388
526
|
|
389
527
|
def json_transform(state)
|
390
|
-
delim = ','
|
391
|
-
delim << state.array_nl
|
392
|
-
result = '['
|
393
|
-
result << state.array_nl
|
394
528
|
depth = state.depth += 1
|
529
|
+
|
530
|
+
if empty?
|
531
|
+
state.depth -= 1
|
532
|
+
return '[]'
|
533
|
+
end
|
534
|
+
|
535
|
+
result = '['.dup
|
536
|
+
if state.array_nl.empty?
|
537
|
+
delim = ","
|
538
|
+
else
|
539
|
+
result << state.array_nl
|
540
|
+
delim = ",#{state.array_nl}"
|
541
|
+
end
|
542
|
+
|
395
543
|
first = true
|
396
544
|
indent = !state.array_nl.empty?
|
397
545
|
each { |value|
|
398
546
|
result << delim unless first
|
399
547
|
result << state.indent * depth if indent
|
400
|
-
if state.strict?
|
401
|
-
|
548
|
+
if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value || Symbol == value)
|
549
|
+
if state.as_json
|
550
|
+
value = state.as_json.call(value)
|
551
|
+
unless false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value || Symbol === value
|
552
|
+
raise GeneratorError.new("#{value.class} returned by #{state.as_json} not allowed in JSON", value)
|
553
|
+
end
|
554
|
+
result << value.to_json(state)
|
555
|
+
else
|
556
|
+
raise GeneratorError.new("#{value.class} not allowed in JSON", value)
|
557
|
+
end
|
402
558
|
elsif value.respond_to?(:to_json)
|
403
559
|
result << value.to_json(state)
|
404
560
|
else
|
@@ -420,20 +576,25 @@ module JSON
|
|
420
576
|
|
421
577
|
module Float
|
422
578
|
# Returns a JSON string representation for this Float number.
|
423
|
-
def to_json(state = nil, *)
|
579
|
+
def to_json(state = nil, *args)
|
424
580
|
state = State.from_state(state)
|
425
|
-
|
426
|
-
when infinite?
|
427
|
-
if state.allow_nan?
|
428
|
-
to_s
|
429
|
-
else
|
430
|
-
raise GeneratorError, "#{self} not allowed in JSON"
|
431
|
-
end
|
432
|
-
when nan?
|
581
|
+
if infinite? || nan?
|
433
582
|
if state.allow_nan?
|
434
583
|
to_s
|
584
|
+
elsif state.strict? && state.as_json
|
585
|
+
casted_value = state.as_json.call(self)
|
586
|
+
|
587
|
+
if casted_value.equal?(self)
|
588
|
+
raise GeneratorError.new("#{self} not allowed in JSON", self)
|
589
|
+
end
|
590
|
+
|
591
|
+
state.check_max_nesting
|
592
|
+
state.depth += 1
|
593
|
+
result = casted_value.to_json(state, *args)
|
594
|
+
state.depth -= 1
|
595
|
+
result
|
435
596
|
else
|
436
|
-
raise GeneratorError
|
597
|
+
raise GeneratorError.new("#{self} not allowed in JSON", self)
|
437
598
|
end
|
438
599
|
else
|
439
600
|
to_s
|
@@ -441,6 +602,17 @@ module JSON
|
|
441
602
|
end
|
442
603
|
end
|
443
604
|
|
605
|
+
module Symbol
|
606
|
+
def to_json(state = nil, *args)
|
607
|
+
state = State.from_state(state)
|
608
|
+
if state.strict?
|
609
|
+
name.to_json(state, *args)
|
610
|
+
else
|
611
|
+
super
|
612
|
+
end
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
444
616
|
module String
|
445
617
|
# This string should be encoded with UTF-8 A call to this method
|
446
618
|
# returns a JSON string encoded with UTF16 big endian characters as
|
@@ -448,15 +620,20 @@ module JSON
|
|
448
620
|
def to_json(state = nil, *args)
|
449
621
|
state = State.from_state(state)
|
450
622
|
if encoding == ::Encoding::UTF_8
|
623
|
+
unless valid_encoding?
|
624
|
+
raise GeneratorError.new("source sequence is illegal/malformed utf-8", self)
|
625
|
+
end
|
451
626
|
string = self
|
452
627
|
else
|
453
628
|
string = encode(::Encoding::UTF_8)
|
454
629
|
end
|
455
630
|
if state.ascii_only?
|
456
|
-
|
631
|
+
%("#{JSON::TruffleRuby::Generator.utf8_to_json_ascii(string, state.script_safe)}")
|
457
632
|
else
|
458
|
-
|
633
|
+
%("#{JSON::TruffleRuby::Generator.utf8_to_json(string, state.script_safe)}")
|
459
634
|
end
|
635
|
+
rescue Encoding::UndefinedConversionError => error
|
636
|
+
raise ::JSON::GeneratorError.new(error.message, self)
|
460
637
|
end
|
461
638
|
|
462
639
|
# Module that holds the extending methods if, the String module is
|
data/lib/json/version.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module JSON
|
3
|
-
|
4
|
-
VERSION = '2.7.2'
|
5
|
-
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
|
6
|
-
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
|
7
|
-
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
|
8
|
-
VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
|
4
|
+
VERSION = '2.10.1'
|
9
5
|
end
|
data/lib/json.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
require 'json/common'
|
3
3
|
|
4
4
|
##
|
@@ -378,13 +378,13 @@ require 'json/common'
|
|
378
378
|
# json1 = JSON.generate(ruby)
|
379
379
|
# ruby1 = JSON.parse(json1, create_additions: true)
|
380
380
|
# # Make a nice display.
|
381
|
-
# display =
|
382
|
-
#
|
383
|
-
#
|
384
|
-
#
|
385
|
-
#
|
386
|
-
#
|
387
|
-
#
|
381
|
+
# display = <<~EOT
|
382
|
+
# Generated JSON:
|
383
|
+
# Without addition: #{json0} (#{json0.class})
|
384
|
+
# With addition: #{json1} (#{json1.class})
|
385
|
+
# Parsed JSON:
|
386
|
+
# Without addition: #{ruby0.inspect} (#{ruby0.class})
|
387
|
+
# With addition: #{ruby1.inspect} (#{ruby1.class})
|
388
388
|
# EOT
|
389
389
|
# puts display
|
390
390
|
#
|
@@ -562,13 +562,13 @@ require 'json/common'
|
|
562
562
|
# json1 = JSON.generate(foo1)
|
563
563
|
# obj1 = JSON.parse(json1, create_additions: true)
|
564
564
|
# # Make a nice display.
|
565
|
-
# display =
|
566
|
-
#
|
567
|
-
#
|
568
|
-
#
|
569
|
-
#
|
570
|
-
#
|
571
|
-
#
|
565
|
+
# display = <<~EOT
|
566
|
+
# Generated JSON:
|
567
|
+
# Without custom addition: #{json0} (#{json0.class})
|
568
|
+
# With custom addition: #{json1} (#{json1.class})
|
569
|
+
# Parsed JSON:
|
570
|
+
# Without custom addition: #{obj0.inspect} (#{obj0.class})
|
571
|
+
# With custom addition: #{obj1.inspect} (#{obj1.class})
|
572
572
|
# EOT
|
573
573
|
# puts display
|
574
574
|
#
|
@@ -583,10 +583,5 @@ require 'json/common'
|
|
583
583
|
#
|
584
584
|
module JSON
|
585
585
|
require 'json/version'
|
586
|
-
|
587
|
-
begin
|
588
|
-
require 'json/ext'
|
589
|
-
rescue LoadError
|
590
|
-
require 'json/pure'
|
591
|
-
end
|
586
|
+
require 'json/ext'
|
592
587
|
end
|