json 2.7.3 → 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/CHANGES.md +61 -0
- data/LEGAL +0 -52
- data/README.md +61 -57
- data/ext/json/ext/fbuffer/fbuffer.h +123 -64
- data/ext/json/ext/generator/generator.c +795 -474
- data/ext/json/ext/parser/extconf.rb +5 -27
- data/ext/json/ext/parser/parser.c +1164 -1923
- data/json.gemspec +7 -5
- data/lib/json/add/bigdecimal.rb +1 -1
- data/lib/json/add/symbol.rb +7 -2
- data/lib/json/common.rb +341 -77
- data/lib/json/ext/generator/state.rb +2 -31
- data/lib/json/ext.rb +28 -11
- data/lib/json/{pure → truffle_ruby}/generator.rb +264 -154
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +15 -20
- metadata +8 -17
- data/ext/json/ext/generator/generator.h +0 -129
- data/ext/json/ext/parser/parser.h +0 -60
- data/ext/json/ext/parser/parser.rl +0 -997
- data/lib/json/pure/parser.rb +0 -331
- data/lib/json/pure.rb +0 -16
data/lib/json/ext.rb
CHANGED
@@ -6,20 +6,37 @@ module JSON
|
|
6
6
|
# This module holds all the modules/classes that implement JSON's
|
7
7
|
# functionality as C extensions.
|
8
8
|
module Ext
|
9
|
+
class Parser
|
10
|
+
class << self
|
11
|
+
def parse(...)
|
12
|
+
new(...).parse
|
13
|
+
end
|
14
|
+
alias_method :parse, :parse # Allow redefinition by extensions
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(source, opts = nil)
|
18
|
+
@source = source
|
19
|
+
@config = Config.new(opts)
|
20
|
+
end
|
21
|
+
|
22
|
+
def source
|
23
|
+
@source.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse
|
27
|
+
@config.parse(@source)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'json/ext/parser'
|
32
|
+
Ext::Parser::Config = Ext::ParserConfig
|
33
|
+
JSON.parser = Ext::Parser
|
34
|
+
|
9
35
|
if RUBY_ENGINE == 'truffleruby'
|
10
|
-
require 'json/
|
11
|
-
|
12
|
-
$DEBUG and warn "Using Ext extension for JSON parser and Pure library for JSON generator."
|
13
|
-
JSON.parser = Parser
|
14
|
-
JSON.generator = JSON::Pure::Generator
|
36
|
+
require 'json/truffle_ruby/generator'
|
37
|
+
JSON.generator = ::JSON::TruffleRuby::Generator
|
15
38
|
else
|
16
|
-
require 'json/ext/parser'
|
17
39
|
require 'json/ext/generator'
|
18
|
-
unless RUBY_ENGINE == 'jruby'
|
19
|
-
require 'json/ext/generator/state'
|
20
|
-
end
|
21
|
-
$DEBUG and warn "Using Ext extension for JSON."
|
22
|
-
JSON.parser = Parser
|
23
40
|
JSON.generator = Generator
|
24
41
|
end
|
25
42
|
end
|
@@ -1,116 +1,123 @@
|
|
1
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
|
-
|
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
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
86
91
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
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
|
93
97
|
|
94
|
-
module Pure
|
95
|
-
module Generator
|
96
98
|
# This class is used to create State instances, that are use to hold data
|
97
99
|
# while generating a JSON text from a Ruby data structure.
|
98
100
|
class State
|
101
|
+
def self.generate(obj, opts = nil, io = nil)
|
102
|
+
new(opts).generate(obj, io)
|
103
|
+
end
|
104
|
+
|
99
105
|
# Creates a State object from _opts_, which ought to be Hash to create
|
100
106
|
# a new State instance configured by _opts_, something else to create
|
101
107
|
# an unconfigured instance. If _opts_ is a State object, it is just
|
102
108
|
# returned.
|
103
109
|
def self.from_state(opts)
|
104
|
-
|
105
|
-
|
106
|
-
opts
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
113
119
|
end
|
120
|
+
SAFE_STATE_PROTOTYPE.dup
|
114
121
|
end
|
115
122
|
|
116
123
|
# Instantiates a new State object, configured by _opts_.
|
@@ -130,7 +137,7 @@ module JSON
|
|
130
137
|
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
131
138
|
# generated, otherwise an exception is thrown, if these values are
|
132
139
|
# encountered. This options defaults to false.
|
133
|
-
def initialize(opts =
|
140
|
+
def initialize(opts = nil)
|
134
141
|
@indent = ''
|
135
142
|
@space = ''
|
136
143
|
@space_before = ''
|
@@ -138,10 +145,13 @@ module JSON
|
|
138
145
|
@array_nl = ''
|
139
146
|
@allow_nan = false
|
140
147
|
@ascii_only = false
|
141
|
-
@
|
142
|
-
@
|
148
|
+
@as_json = false
|
149
|
+
@depth = 0
|
143
150
|
@buffer_initial_length = 1024
|
144
|
-
|
151
|
+
@script_safe = false
|
152
|
+
@strict = false
|
153
|
+
@max_nesting = 100
|
154
|
+
configure(opts) if opts
|
145
155
|
end
|
146
156
|
|
147
157
|
# This string is used to indent levels in the JSON text.
|
@@ -161,6 +171,9 @@ module JSON
|
|
161
171
|
# This string is put at the end of a line that holds a JSON array.
|
162
172
|
attr_accessor :array_nl
|
163
173
|
|
174
|
+
# This proc converts unsupported types into native JSON types.
|
175
|
+
attr_accessor :as_json
|
176
|
+
|
164
177
|
# This integer returns the maximum level of data structure nesting in
|
165
178
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
166
179
|
attr_accessor :max_nesting
|
@@ -239,13 +252,14 @@ module JSON
|
|
239
252
|
end
|
240
253
|
|
241
254
|
# NOTE: If adding new instance variables here, check whether #generate should check them for #generate_json
|
242
|
-
@indent = opts[:indent] if opts.key?(:indent)
|
243
|
-
@space = opts[:space] if opts.key?(:space)
|
244
|
-
@space_before = opts[:space_before] if opts.key?(:space_before)
|
245
|
-
@object_nl = opts[:object_nl] if opts.key?(:object_nl)
|
246
|
-
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
|
247
|
-
@allow_nan = !!opts[:allow_nan]
|
248
|
-
@
|
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)
|
249
263
|
@depth = opts[:depth] || 0
|
250
264
|
@buffer_initial_length ||= opts[:buffer_initial_length]
|
251
265
|
|
@@ -287,16 +301,27 @@ module JSON
|
|
287
301
|
# returns the result. If no valid JSON document can be
|
288
302
|
# created this method raises a
|
289
303
|
# GeneratorError exception.
|
290
|
-
def generate(obj)
|
304
|
+
def generate(obj, anIO = nil)
|
291
305
|
if @indent.empty? and @space.empty? and @space_before.empty? and @object_nl.empty? and @array_nl.empty? and
|
292
|
-
!@ascii_only and !@script_safe and @max_nesting == 0 and !@strict
|
306
|
+
!@ascii_only and !@script_safe and @max_nesting == 0 and (!@strict || Symbol === obj)
|
293
307
|
result = generate_json(obj, ''.dup)
|
294
308
|
else
|
295
309
|
result = obj.to_json(self)
|
296
310
|
end
|
297
|
-
JSON.valid_utf8?(result) or raise GeneratorError
|
298
|
-
"source sequence #{result.inspect} is illegal/malformed utf-8"
|
299
|
-
|
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)
|
300
325
|
end
|
301
326
|
|
302
327
|
# Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
|
@@ -307,7 +332,16 @@ module JSON
|
|
307
332
|
first = true
|
308
333
|
obj.each_pair do |k,v|
|
309
334
|
buf << ',' unless first
|
310
|
-
|
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
|
+
|
311
345
|
buf << ':'
|
312
346
|
generate_json(v, buf)
|
313
347
|
first = false
|
@@ -323,9 +357,19 @@ module JSON
|
|
323
357
|
end
|
324
358
|
buf << ']'
|
325
359
|
when String
|
326
|
-
|
360
|
+
if obj.class == String
|
361
|
+
fast_serialize_string(obj, buf)
|
362
|
+
else
|
363
|
+
buf << obj.to_json(self)
|
364
|
+
end
|
327
365
|
when Integer
|
328
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
|
329
373
|
else
|
330
374
|
# Note: Float is handled this way since Float#to_s is slow anyway
|
331
375
|
buf << obj.to_json(self)
|
@@ -333,24 +377,23 @@ module JSON
|
|
333
377
|
end
|
334
378
|
|
335
379
|
# Assumes !@ascii_only, !@script_safe
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
buf << string.gsub(/["\\\x0-\x1f]/n, MAP)
|
344
|
-
else
|
345
|
-
buf << string
|
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)
|
346
387
|
end
|
347
|
-
buf << '"'
|
348
388
|
end
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
buf << string.
|
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
|
353
395
|
end
|
396
|
+
buf << '"'
|
354
397
|
end
|
355
398
|
|
356
399
|
# Return the value returned by method +name+.
|
@@ -378,8 +421,20 @@ module JSON
|
|
378
421
|
# it to a JSON string, and returns the result. This is a fallback, if no
|
379
422
|
# special method #to_json was defined for some object.
|
380
423
|
def to_json(state = nil, *)
|
381
|
-
|
382
|
-
|
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
|
383
438
|
else
|
384
439
|
to_s.to_json
|
385
440
|
end
|
@@ -406,17 +461,39 @@ module JSON
|
|
406
461
|
end
|
407
462
|
|
408
463
|
def json_transform(state)
|
464
|
+
depth = state.depth += 1
|
465
|
+
|
466
|
+
if empty?
|
467
|
+
state.depth -= 1
|
468
|
+
return '{}'
|
469
|
+
end
|
470
|
+
|
409
471
|
delim = ",#{state.object_nl}"
|
410
472
|
result = +"{#{state.object_nl}"
|
411
|
-
depth = state.depth += 1
|
412
473
|
first = true
|
413
474
|
indent = !state.object_nl.empty?
|
414
475
|
each { |key, value|
|
415
476
|
result << delim unless first
|
416
477
|
result << state.indent * depth if indent
|
417
|
-
|
418
|
-
|
419
|
-
|
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
|
420
497
|
elsif value.respond_to?(:to_json)
|
421
498
|
result << value.to_json(state)
|
422
499
|
else
|
@@ -448,6 +525,13 @@ module JSON
|
|
448
525
|
private
|
449
526
|
|
450
527
|
def json_transform(state)
|
528
|
+
depth = state.depth += 1
|
529
|
+
|
530
|
+
if empty?
|
531
|
+
state.depth -= 1
|
532
|
+
return '[]'
|
533
|
+
end
|
534
|
+
|
451
535
|
result = '['.dup
|
452
536
|
if state.array_nl.empty?
|
453
537
|
delim = ","
|
@@ -455,14 +539,22 @@ module JSON
|
|
455
539
|
result << state.array_nl
|
456
540
|
delim = ",#{state.array_nl}"
|
457
541
|
end
|
458
|
-
|
542
|
+
|
459
543
|
first = true
|
460
544
|
indent = !state.array_nl.empty?
|
461
545
|
each { |value|
|
462
546
|
result << delim unless first
|
463
547
|
result << state.indent * depth if indent
|
464
|
-
if state.strict? && !(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value)
|
465
|
-
|
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
|
466
558
|
elsif value.respond_to?(:to_json)
|
467
559
|
result << value.to_json(state)
|
468
560
|
else
|
@@ -484,20 +576,25 @@ module JSON
|
|
484
576
|
|
485
577
|
module Float
|
486
578
|
# Returns a JSON string representation for this Float number.
|
487
|
-
def to_json(state = nil, *)
|
579
|
+
def to_json(state = nil, *args)
|
488
580
|
state = State.from_state(state)
|
489
|
-
|
490
|
-
when infinite?
|
581
|
+
if infinite? || nan?
|
491
582
|
if state.allow_nan?
|
492
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
|
493
596
|
else
|
494
|
-
raise GeneratorError
|
495
|
-
end
|
496
|
-
when nan?
|
497
|
-
if state.allow_nan?
|
498
|
-
to_s
|
499
|
-
else
|
500
|
-
raise GeneratorError, "#{self} not allowed in JSON"
|
597
|
+
raise GeneratorError.new("#{self} not allowed in JSON", self)
|
501
598
|
end
|
502
599
|
else
|
503
600
|
to_s
|
@@ -505,6 +602,17 @@ module JSON
|
|
505
602
|
end
|
506
603
|
end
|
507
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
|
+
|
508
616
|
module String
|
509
617
|
# This string should be encoded with UTF-8 A call to this method
|
510
618
|
# returns a JSON string encoded with UTF16 big endian characters as
|
@@ -513,17 +621,19 @@ module JSON
|
|
513
621
|
state = State.from_state(state)
|
514
622
|
if encoding == ::Encoding::UTF_8
|
515
623
|
unless valid_encoding?
|
516
|
-
raise GeneratorError
|
624
|
+
raise GeneratorError.new("source sequence is illegal/malformed utf-8", self)
|
517
625
|
end
|
518
626
|
string = self
|
519
627
|
else
|
520
628
|
string = encode(::Encoding::UTF_8)
|
521
629
|
end
|
522
630
|
if state.ascii_only?
|
523
|
-
%("#{JSON.utf8_to_json_ascii(string, state.script_safe)}")
|
631
|
+
%("#{JSON::TruffleRuby::Generator.utf8_to_json_ascii(string, state.script_safe)}")
|
524
632
|
else
|
525
|
-
%("#{JSON.utf8_to_json(string, state.script_safe)}")
|
633
|
+
%("#{JSON::TruffleRuby::Generator.utf8_to_json(string, state.script_safe)}")
|
526
634
|
end
|
635
|
+
rescue Encoding::UndefinedConversionError => error
|
636
|
+
raise ::JSON::GeneratorError.new(error.message, self)
|
527
637
|
end
|
528
638
|
|
529
639
|
# Module that holds the extending methods if, the String module is
|
data/lib/json/version.rb
CHANGED