json 1.8.3 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of json might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +7 -10
- data/{CHANGES → CHANGES.md} +186 -90
- data/Gemfile +10 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +184 -133
- data/Rakefile +33 -37
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +0 -3
- data/ext/json/ext/generator/generator.c +47 -61
- data/ext/json/ext/generator/generator.h +7 -2
- data/ext/json/ext/parser/extconf.rb +3 -0
- data/ext/json/ext/parser/parser.c +374 -459
- data/ext/json/ext/parser/parser.h +4 -5
- data/ext/json/ext/parser/parser.rl +133 -181
- data/ext/json/extconf.rb +0 -1
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +11 -12
- data/java/src/json/ext/GeneratorMethods.java +1 -2
- data/java/src/json/ext/GeneratorService.java +1 -2
- data/java/src/json/ext/GeneratorState.java +3 -56
- data/java/src/json/ext/OptionsReader.java +2 -3
- data/java/src/json/ext/Parser.java +132 -415
- data/java/src/json/ext/Parser.rl +48 -124
- data/java/src/json/ext/ParserService.java +1 -2
- data/java/src/json/ext/RuntimeInfo.java +1 -6
- data/java/src/json/ext/StringDecoder.java +1 -2
- data/java/src/json/ext/StringEncoder.java +5 -0
- data/java/src/json/ext/Utils.java +1 -2
- data/json-java.gemspec +15 -0
- data/json.gemspec +0 -0
- data/json_pure.gemspec +24 -26
- data/lib/json/add/bigdecimal.rb +1 -0
- data/lib/json/add/complex.rb +2 -1
- data/lib/json/add/core.rb +1 -0
- 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 +3 -3
- data/lib/json/add/range.rb +1 -1
- data/lib/json/add/rational.rb +1 -0
- data/lib/json/add/regexp.rb +1 -1
- data/lib/json/add/set.rb +29 -0
- data/lib/json/add/struct.rb +1 -1
- data/lib/json/add/symbol.rb +1 -1
- data/lib/json/add/time.rb +1 -1
- data/lib/json/common.rb +24 -52
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +5 -4
- data/lib/json/pure/generator.rb +61 -125
- data/lib/json/pure/parser.rb +33 -81
- data/lib/json/pure.rb +2 -8
- data/lib/json/version.rb +2 -1
- data/lib/json.rb +1 -0
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +32 -25
- data/tests/json_common_interface_test.rb +126 -0
- data/tests/json_encoding_test.rb +107 -0
- data/tests/json_ext_parser_test.rb +15 -0
- data/tests/{test_json_fixtures.rb → json_fixtures_test.rb} +5 -8
- data/tests/{test_json_generate.rb → json_generator_test.rb} +79 -39
- data/tests/{test_json_generic_object.rb → json_generic_object_test.rb} +15 -8
- data/tests/json_parser_test.rb +472 -0
- data/tests/json_string_matching_test.rb +38 -0
- data/tests/{setup_variant.rb → test_helper.rb} +6 -0
- data/tools/diff.sh +18 -0
- data/tools/fuzz.rb +1 -9
- metadata +29 -47
- data/COPYING +0 -58
- data/COPYING-json-jruby +0 -57
- data/GPL +0 -340
- data/TODO +0 -1
- data/data/example.json +0 -1
- data/data/index.html +0 -38
- data/data/prototype.js +0 -4184
- data/tests/fixtures/fail1.json +0 -1
- data/tests/test_json.rb +0 -553
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_string_matching.rb +0 -39
- data/tests/test_json_unicode.rb +0 -72
data/lib/json/add/time.rb
CHANGED
data/lib/json/common.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
+
#frozen_string_literal: false
|
1
2
|
require 'json/version'
|
2
3
|
require 'json/generic_object'
|
3
4
|
|
4
5
|
module JSON
|
5
6
|
class << self
|
6
|
-
# If _object_ is string-like, parse the string and return the parsed
|
7
|
-
# as a Ruby data structure. Otherwise generate a JSON text from the
|
8
|
-
# data structure object and return it.
|
7
|
+
# If _object_ is string-like, parse the string and return the parsed
|
8
|
+
# result as a Ruby data structure. Otherwise generate a JSON text from the
|
9
|
+
# Ruby data structure object and return it.
|
9
10
|
#
|
10
|
-
# The _opts_ argument is passed through to generate/parse respectively.
|
11
|
-
# generate and parse for their documentation.
|
11
|
+
# The _opts_ argument is passed through to generate/parse respectively.
|
12
|
+
# See generate and parse for their documentation.
|
12
13
|
def [](object, opts = {})
|
13
14
|
if object.respond_to? :to_str
|
14
15
|
JSON.parse(object.to_str, opts)
|
@@ -24,7 +25,7 @@ module JSON
|
|
24
25
|
# Set the JSON parser class _parser_ to be used by JSON.
|
25
26
|
def parser=(parser) # :nodoc:
|
26
27
|
@parser = parser
|
27
|
-
remove_const :Parser if
|
28
|
+
remove_const :Parser if const_defined?(:Parser, false)
|
28
29
|
const_set :Parser, parser
|
29
30
|
end
|
30
31
|
|
@@ -35,8 +36,8 @@ module JSON
|
|
35
36
|
def deep_const_get(path) # :nodoc:
|
36
37
|
path.to_s.split(/::/).inject(Object) do |p, c|
|
37
38
|
case
|
38
|
-
when c.empty?
|
39
|
-
when
|
39
|
+
when c.empty? then p
|
40
|
+
when p.const_defined?(c, true) then p.const_get(c)
|
40
41
|
else
|
41
42
|
begin
|
42
43
|
p.const_missing(c)
|
@@ -138,10 +139,10 @@ module JSON
|
|
138
139
|
# _opts_ can have the following
|
139
140
|
# keys:
|
140
141
|
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
|
141
|
-
# structures. Disable depth checking with :max_nesting => false. It
|
142
|
-
# to 100.
|
142
|
+
# structures. Disable depth checking with :max_nesting => false. It
|
143
|
+
# defaults to 100.
|
143
144
|
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
|
144
|
-
# defiance of RFC
|
145
|
+
# defiance of RFC 7159 to be parsed by the Parser. This option defaults
|
145
146
|
# to false.
|
146
147
|
# * *symbolize_names*: If set to true, returns symbols for the names
|
147
148
|
# (keys) in a JSON object. Otherwise strings are returned. Strings are
|
@@ -161,11 +162,11 @@ module JSON
|
|
161
162
|
#
|
162
163
|
# _opts_ can have the following keys:
|
163
164
|
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
|
164
|
-
# structures. Enable depth checking with :max_nesting => anInteger. The
|
165
|
-
# methods defaults to not doing max depth checking: This can be
|
166
|
-
# if someone wants to fill up your stack.
|
165
|
+
# structures. Enable depth checking with :max_nesting => anInteger. The
|
166
|
+
# parse! methods defaults to not doing max depth checking: This can be
|
167
|
+
# dangerous if someone wants to fill up your stack.
|
167
168
|
# * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
|
168
|
-
# defiance of RFC
|
169
|
+
# defiance of RFC 7159 to be parsed by the Parser. This option defaults
|
169
170
|
# to true.
|
170
171
|
# * *create_additions*: If set to false, the Parser doesn't create
|
171
172
|
# additions even if a matching class and create_id was found. This option
|
@@ -174,7 +175,7 @@ module JSON
|
|
174
175
|
opts = {
|
175
176
|
:max_nesting => false,
|
176
177
|
:allow_nan => true
|
177
|
-
}.
|
178
|
+
}.merge(opts)
|
178
179
|
Parser.new(source, opts).parse
|
179
180
|
end
|
180
181
|
|
@@ -295,13 +296,13 @@ module JSON
|
|
295
296
|
# The global default options for the JSON.load method:
|
296
297
|
# :max_nesting: false
|
297
298
|
# :allow_nan: true
|
298
|
-
# :
|
299
|
+
# :allow_blank: true
|
299
300
|
attr_accessor :load_default_options
|
300
301
|
end
|
301
302
|
self.load_default_options = {
|
302
303
|
:max_nesting => false,
|
303
304
|
:allow_nan => true,
|
304
|
-
:
|
305
|
+
:allow_blank => true,
|
305
306
|
:create_additions => true,
|
306
307
|
}
|
307
308
|
|
@@ -328,7 +329,7 @@ module JSON
|
|
328
329
|
elsif source.respond_to?(:read)
|
329
330
|
source = source.read
|
330
331
|
end
|
331
|
-
if opts[:
|
332
|
+
if opts[:allow_blank] && (source.nil? || source.empty?)
|
332
333
|
source = 'null'
|
333
334
|
end
|
334
335
|
result = parse(source, opts)
|
@@ -357,13 +358,12 @@ module JSON
|
|
357
358
|
# The global default options for the JSON.dump method:
|
358
359
|
# :max_nesting: false
|
359
360
|
# :allow_nan: true
|
360
|
-
# :
|
361
|
+
# :allow_blank: true
|
361
362
|
attr_accessor :dump_default_options
|
362
363
|
end
|
363
364
|
self.dump_default_options = {
|
364
365
|
:max_nesting => false,
|
365
366
|
:allow_nan => true,
|
366
|
-
:quirks_mode => true,
|
367
367
|
}
|
368
368
|
|
369
369
|
# Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
|
@@ -402,37 +402,9 @@ module JSON
|
|
402
402
|
raise ArgumentError, "exceed depth limit"
|
403
403
|
end
|
404
404
|
|
405
|
-
#
|
406
|
-
def self.
|
407
|
-
|
408
|
-
break unless string[2 * i + 1]
|
409
|
-
string[2 * i], string[2 * i + 1] = string[2 * i + 1], string[2 * i]
|
410
|
-
end
|
411
|
-
string
|
412
|
-
end
|
413
|
-
|
414
|
-
# Shortcut for iconv.
|
415
|
-
if ::String.method_defined?(:encode)
|
416
|
-
# Encodes string using Ruby's _String.encode_
|
417
|
-
def self.iconv(to, from, string)
|
418
|
-
string.encode(to, from)
|
419
|
-
end
|
420
|
-
else
|
421
|
-
require 'iconv'
|
422
|
-
# Encodes string using _iconv_ library
|
423
|
-
def self.iconv(to, from, string)
|
424
|
-
Iconv.conv(to, from, string)
|
425
|
-
end
|
426
|
-
end
|
427
|
-
|
428
|
-
if ::Object.method(:const_defined?).arity == 1
|
429
|
-
def self.const_defined_in?(modul, constant)
|
430
|
-
modul.const_defined?(constant)
|
431
|
-
end
|
432
|
-
else
|
433
|
-
def self.const_defined_in?(modul, constant)
|
434
|
-
modul.const_defined?(constant, false)
|
435
|
-
end
|
405
|
+
# Encodes string using Ruby's _String.encode_
|
406
|
+
def self.iconv(to, from, string)
|
407
|
+
string.encode(to, from)
|
436
408
|
end
|
437
409
|
end
|
438
410
|
|
data/lib/json/ext.rb
CHANGED
data/lib/json/generic_object.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#frozen_string_literal: false
|
1
2
|
require 'ostruct'
|
2
3
|
|
3
4
|
module JSON
|
@@ -48,12 +49,12 @@ module JSON
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def [](name)
|
51
|
-
|
52
|
-
end
|
52
|
+
__send__(name)
|
53
|
+
end unless method_defined?(:[])
|
53
54
|
|
54
55
|
def []=(name, value)
|
55
|
-
__send__
|
56
|
-
end
|
56
|
+
__send__("#{name}=", value)
|
57
|
+
end unless method_defined?(:[]=)
|
57
58
|
|
58
59
|
def |(other)
|
59
60
|
self.class[other.to_hash.merge(to_hash)]
|
data/lib/json/pure/generator.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#frozen_string_literal: false
|
1
2
|
module JSON
|
2
3
|
MAP = {
|
3
4
|
"\x0" => '\u0000',
|
@@ -38,85 +39,45 @@ module JSON
|
|
38
39
|
|
39
40
|
# Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
|
40
41
|
# UTF16 big endian characters as \u????, and return it.
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
def utf8_to_json_ascii(string) # :nodoc:
|
51
|
-
string = string.dup
|
52
|
-
string.force_encoding(::Encoding::ASCII_8BIT)
|
53
|
-
string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
|
54
|
-
string.gsub!(/(
|
55
|
-
(?:
|
56
|
-
[\xc2-\xdf][\x80-\xbf] |
|
57
|
-
[\xe0-\xef][\x80-\xbf]{2} |
|
58
|
-
[\xf0-\xf4][\x80-\xbf]{3}
|
59
|
-
)+ |
|
60
|
-
[\x80-\xc1\xf5-\xff] # invalid
|
61
|
-
)/nx) { |c|
|
62
|
-
c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
|
63
|
-
s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
|
64
|
-
s.force_encoding(::Encoding::ASCII_8BIT)
|
65
|
-
s.gsub!(/.{4}/n, '\\\\u\&')
|
66
|
-
s.force_encoding(::Encoding::UTF_8)
|
67
|
-
}
|
68
|
-
string.force_encoding(::Encoding::UTF_8)
|
69
|
-
string
|
70
|
-
rescue => e
|
71
|
-
raise GeneratorError.wrap(e)
|
72
|
-
end
|
73
|
-
|
74
|
-
def valid_utf8?(string)
|
75
|
-
encoding = string.encoding
|
76
|
-
(encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
|
77
|
-
string.valid_encoding?
|
78
|
-
end
|
79
|
-
module_function :valid_utf8?
|
80
|
-
else
|
81
|
-
def utf8_to_json(string) # :nodoc:
|
82
|
-
string.gsub(/["\\\x0-\x1f]/n) { MAP[$&] }
|
83
|
-
end
|
42
|
+
def utf8_to_json(string) # :nodoc:
|
43
|
+
string = string.dup
|
44
|
+
string.force_encoding(::Encoding::ASCII_8BIT)
|
45
|
+
string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
|
46
|
+
string.force_encoding(::Encoding::UTF_8)
|
47
|
+
string
|
48
|
+
end
|
84
49
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
50
|
+
def utf8_to_json_ascii(string) # :nodoc:
|
51
|
+
string = string.dup
|
52
|
+
string.force_encoding(::Encoding::ASCII_8BIT)
|
53
|
+
string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
|
54
|
+
string.gsub!(/(
|
55
|
+
(?:
|
56
|
+
[\xc2-\xdf][\x80-\xbf] |
|
57
|
+
[\xe0-\xef][\x80-\xbf]{2} |
|
58
|
+
[\xf0-\xf4][\x80-\xbf]{3}
|
59
|
+
)+ |
|
60
|
+
[\x80-\xc1\xf5-\xff] # invalid
|
61
|
+
)/nx) { |c|
|
62
|
+
c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
|
63
|
+
s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
|
64
|
+
s.force_encoding(::Encoding::ASCII_8BIT)
|
65
|
+
s.gsub!(/.{4}/n, '\\\\u\&')
|
66
|
+
s.force_encoding(::Encoding::UTF_8)
|
67
|
+
}
|
68
|
+
string.force_encoding(::Encoding::UTF_8)
|
69
|
+
string
|
70
|
+
rescue => e
|
71
|
+
raise GeneratorError.wrap(e)
|
72
|
+
end
|
103
73
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
| \xe0[\xa0-\xbf][\x80-\xbf] # excluding overlongs
|
109
|
-
| [\xe1-\xec\xee\xef][\x80-\xbf]{2} # straight 3-byte
|
110
|
-
| \xed[\x80-\x9f][\x80-\xbf] # excluding surrogates
|
111
|
-
| \xf0[\x90-\xbf][\x80-\xbf]{2} # planes 1-3
|
112
|
-
| [\xf1-\xf3][\x80-\xbf]{3} # planes 4-15
|
113
|
-
| \xf4[\x80-\x8f][\x80-\xbf]{2} # plane 16
|
114
|
-
)*\z/nx
|
115
|
-
end
|
74
|
+
def valid_utf8?(string)
|
75
|
+
encoding = string.encoding
|
76
|
+
(encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
|
77
|
+
string.valid_encoding?
|
116
78
|
end
|
117
79
|
module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
|
118
80
|
|
119
|
-
|
120
81
|
module Pure
|
121
82
|
module Generator
|
122
83
|
# This class is used to create State instances, that are use to hold data
|
@@ -154,8 +115,6 @@ module JSON
|
|
154
115
|
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
155
116
|
# generated, otherwise an exception is thrown, if these values are
|
156
117
|
# encountered. This options defaults to false.
|
157
|
-
# * *quirks_mode*: Enables quirks_mode for parser, that is for example
|
158
|
-
# generating single JSON values instead of documents is possible.
|
159
118
|
def initialize(opts = {})
|
160
119
|
@indent = ''
|
161
120
|
@space = ''
|
@@ -164,7 +123,6 @@ module JSON
|
|
164
123
|
@array_nl = ''
|
165
124
|
@allow_nan = false
|
166
125
|
@ascii_only = false
|
167
|
-
@quirks_mode = false
|
168
126
|
@buffer_initial_length = 1024
|
169
127
|
configure opts
|
170
128
|
end
|
@@ -190,10 +148,6 @@ module JSON
|
|
190
148
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
191
149
|
attr_accessor :max_nesting
|
192
150
|
|
193
|
-
# If this attribute is set to true, quirks mode is enabled, otherwise
|
194
|
-
# it's disabled.
|
195
|
-
attr_accessor :quirks_mode
|
196
|
-
|
197
151
|
# :stopdoc:
|
198
152
|
attr_reader :buffer_initial_length
|
199
153
|
|
@@ -233,11 +187,6 @@ module JSON
|
|
233
187
|
@ascii_only
|
234
188
|
end
|
235
189
|
|
236
|
-
# Returns true, if quirks mode is enabled. Otherwise returns false.
|
237
|
-
def quirks_mode?
|
238
|
-
@quirks_mode
|
239
|
-
end
|
240
|
-
|
241
190
|
# Configure this State instance with the Hash _opts_, and return
|
242
191
|
# itself.
|
243
192
|
def configure(opts)
|
@@ -259,7 +208,6 @@ module JSON
|
|
259
208
|
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
260
209
|
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
261
210
|
@depth = opts[:depth] || 0
|
262
|
-
@quirks_mode = opts[:quirks_mode] if opts.key?(:quirks_mode)
|
263
211
|
@buffer_initial_length ||= opts[:buffer_initial_length]
|
264
212
|
|
265
213
|
if !opts.key?(:max_nesting) # defaults to 100
|
@@ -286,20 +234,14 @@ module JSON
|
|
286
234
|
|
287
235
|
alias to_hash to_h
|
288
236
|
|
289
|
-
# Generates a valid JSON document from object +obj+ and
|
290
|
-
# result. If no valid JSON document can be
|
237
|
+
# Generates a valid JSON document from object +obj+ and
|
238
|
+
# returns the result. If no valid JSON document can be
|
239
|
+
# created this method raises a
|
291
240
|
# GeneratorError exception.
|
292
241
|
def generate(obj)
|
293
242
|
result = obj.to_json(self)
|
294
243
|
JSON.valid_utf8?(result) or raise GeneratorError,
|
295
244
|
"source sequence #{result.inspect} is illegal/malformed utf-8"
|
296
|
-
unless @quirks_mode
|
297
|
-
unless result =~ /\A\s*\[/ && result =~ /\]\s*\Z/ ||
|
298
|
-
result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
|
299
|
-
then
|
300
|
-
raise GeneratorError, "only generation of JSON objects or arrays allowed"
|
301
|
-
end
|
302
|
-
end
|
303
245
|
result
|
304
246
|
end
|
305
247
|
|
@@ -363,7 +305,11 @@ module JSON
|
|
363
305
|
result << state.space_before
|
364
306
|
result << ':'
|
365
307
|
result << state.space
|
366
|
-
|
308
|
+
if value.respond_to?(:to_json)
|
309
|
+
result << value.to_json(state)
|
310
|
+
else
|
311
|
+
result << %{"#{String(value)}"}
|
312
|
+
end
|
367
313
|
first = false
|
368
314
|
}
|
369
315
|
depth = state.depth -= 1
|
@@ -398,7 +344,11 @@ module JSON
|
|
398
344
|
each { |value|
|
399
345
|
result << delim unless first
|
400
346
|
result << state.indent * depth if indent
|
401
|
-
|
347
|
+
if value.respond_to?(:to_json)
|
348
|
+
result << value.to_json(state)
|
349
|
+
else
|
350
|
+
result << %{"#{String(value)}"}
|
351
|
+
end
|
402
352
|
first = false
|
403
353
|
}
|
404
354
|
depth = state.depth -= 1
|
@@ -437,34 +387,20 @@ module JSON
|
|
437
387
|
end
|
438
388
|
|
439
389
|
module String
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
string = encode(::Encoding::UTF_8)
|
450
|
-
end
|
451
|
-
if state.ascii_only?
|
452
|
-
'"' << JSON.utf8_to_json_ascii(string) << '"'
|
453
|
-
else
|
454
|
-
'"' << JSON.utf8_to_json(string) << '"'
|
455
|
-
end
|
390
|
+
# This string should be encoded with UTF-8 A call to this method
|
391
|
+
# returns a JSON string encoded with UTF16 big endian characters as
|
392
|
+
# \u????.
|
393
|
+
def to_json(state = nil, *args)
|
394
|
+
state = State.from_state(state)
|
395
|
+
if encoding == ::Encoding::UTF_8
|
396
|
+
string = self
|
397
|
+
else
|
398
|
+
string = encode(::Encoding::UTF_8)
|
456
399
|
end
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
def to_json(state = nil, *args)
|
462
|
-
state = State.from_state(state)
|
463
|
-
if state.ascii_only?
|
464
|
-
'"' << JSON.utf8_to_json_ascii(self) << '"'
|
465
|
-
else
|
466
|
-
'"' << JSON.utf8_to_json(self) << '"'
|
467
|
-
end
|
400
|
+
if state.ascii_only?
|
401
|
+
'"' << JSON.utf8_to_json_ascii(string) << '"'
|
402
|
+
else
|
403
|
+
'"' << JSON.utf8_to_json(string) << '"'
|
468
404
|
end
|
469
405
|
end
|
470
406
|
|
data/lib/json/pure/parser.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
#frozen_string_literal: false
|
1
2
|
require 'strscan'
|
2
3
|
|
3
4
|
module JSON
|
@@ -48,7 +49,7 @@ module JSON
|
|
48
49
|
)+
|
49
50
|
)mx
|
50
51
|
|
51
|
-
|
52
|
+
UNPARSED = Object.new.freeze
|
52
53
|
|
53
54
|
# Creates a new JSON::Pure::Parser instance for the string _source_.
|
54
55
|
#
|
@@ -58,23 +59,23 @@ module JSON
|
|
58
59
|
# structures. Disable depth checking with :max_nesting => false|nil|0,
|
59
60
|
# it defaults to 100.
|
60
61
|
# * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
|
61
|
-
# defiance of RFC
|
62
|
+
# defiance of RFC 7159 to be parsed by the Parser. This option defaults
|
62
63
|
# to false.
|
63
64
|
# * *symbolize_names*: If set to true, returns symbols for the names
|
64
|
-
# (keys) in a JSON object. Otherwise strings are returned, which is
|
65
|
-
# the default.
|
65
|
+
# (keys) in a JSON object. Otherwise strings are returned, which is
|
66
|
+
# also the default. It's not possible to use this option in
|
67
|
+
# conjunction with the *create_additions* option.
|
66
68
|
# * *create_additions*: If set to true, the Parser creates
|
67
69
|
# additions when if a matching class and create_id was found. This
|
68
70
|
# option defaults to false.
|
69
71
|
# * *object_class*: Defaults to Hash
|
70
72
|
# * *array_class*: Defaults to Array
|
71
|
-
# * *
|
72
|
-
#
|
73
|
+
# * *decimal_class*: Specifies which class to use instead of the default
|
74
|
+
# (Float) when parsing decimal numbers. This class must accept a single
|
75
|
+
# string argument in its constructor.
|
73
76
|
def initialize(source, opts = {})
|
74
77
|
opts ||= {}
|
75
|
-
|
76
|
-
source = convert_encoding source
|
77
|
-
end
|
78
|
+
source = convert_encoding source
|
78
79
|
super source
|
79
80
|
if !opts.key?(:max_nesting) # defaults to 100
|
80
81
|
@max_nesting = 100
|
@@ -90,56 +91,38 @@ module JSON
|
|
90
91
|
else
|
91
92
|
@create_additions = false
|
92
93
|
end
|
94
|
+
@symbolize_names && @create_additions and raise ArgumentError,
|
95
|
+
'options :symbolize_names and :create_additions cannot be used '\
|
96
|
+
'in conjunction'
|
93
97
|
@create_id = @create_additions ? JSON.create_id : nil
|
94
98
|
@object_class = opts[:object_class] || Hash
|
95
99
|
@array_class = opts[:array_class] || Array
|
100
|
+
@decimal_class = opts[:decimal_class]
|
96
101
|
@match_string = opts[:match_string]
|
97
102
|
end
|
98
103
|
|
99
104
|
alias source string
|
100
105
|
|
101
|
-
def quirks_mode?
|
102
|
-
!!@quirks_mode
|
103
|
-
end
|
104
|
-
|
105
106
|
def reset
|
106
107
|
super
|
107
108
|
@current_nesting = 0
|
108
109
|
end
|
109
110
|
|
110
|
-
# Parses the current JSON string _source_ and returns the
|
111
|
-
# structure as a result.
|
111
|
+
# Parses the current JSON string _source_ and returns the
|
112
|
+
# complete data structure as a result.
|
112
113
|
def parse
|
113
114
|
reset
|
114
115
|
obj = nil
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
if eos?
|
119
|
-
raise ParserError, "source did not contain any JSON!"
|
120
|
-
else
|
121
|
-
obj = parse_value
|
122
|
-
obj == UNPARSED and raise ParserError, "source did not contain any JSON!"
|
123
|
-
end
|
116
|
+
while !eos? && skip(IGNORE) do end
|
117
|
+
if eos?
|
118
|
+
raise ParserError, "source is not valid JSON!"
|
124
119
|
else
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
|
129
|
-
@current_nesting = 1
|
130
|
-
obj = parse_object
|
131
|
-
when scan(ARRAY_OPEN)
|
132
|
-
obj and raise ParserError, "source '#{peek(20)}' not in JSON!"
|
133
|
-
@current_nesting = 1
|
134
|
-
obj = parse_array
|
135
|
-
when skip(IGNORE)
|
136
|
-
;
|
137
|
-
else
|
138
|
-
raise ParserError, "source '#{peek(20)}' not in JSON!"
|
139
|
-
end
|
140
|
-
end
|
141
|
-
obj or raise ParserError, "source did not contain any JSON!"
|
120
|
+
obj = parse_value
|
121
|
+
UNPARSED.equal?(obj) and raise ParserError,
|
122
|
+
"source is not valid JSON!"
|
142
123
|
end
|
124
|
+
while !eos? && skip(IGNORE) do end
|
125
|
+
eos? or raise ParserError, "source is not valid JSON!"
|
143
126
|
obj
|
144
127
|
end
|
145
128
|
|
@@ -149,43 +132,12 @@ module JSON
|
|
149
132
|
if source.respond_to?(:to_str)
|
150
133
|
source = source.to_str
|
151
134
|
else
|
152
|
-
raise TypeError,
|
135
|
+
raise TypeError,
|
136
|
+
"#{source.inspect} is not like a string"
|
153
137
|
end
|
154
|
-
if
|
155
|
-
|
156
|
-
b = source[0, 4].bytes.to_a
|
157
|
-
source =
|
158
|
-
case
|
159
|
-
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
160
|
-
source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
|
161
|
-
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
162
|
-
source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
|
163
|
-
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
164
|
-
source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
|
165
|
-
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
166
|
-
source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
|
167
|
-
else
|
168
|
-
source.dup
|
169
|
-
end
|
170
|
-
else
|
171
|
-
source = source.encode(::Encoding::UTF_8)
|
172
|
-
end
|
138
|
+
if source.encoding != ::Encoding::ASCII_8BIT
|
139
|
+
source = source.encode(::Encoding::UTF_8)
|
173
140
|
source.force_encoding(::Encoding::ASCII_8BIT)
|
174
|
-
else
|
175
|
-
b = source
|
176
|
-
source =
|
177
|
-
case
|
178
|
-
when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0
|
179
|
-
JSON.iconv('utf-8', 'utf-32be', b)
|
180
|
-
when b.size >= 4 && b[0] == 0 && b[2] == 0
|
181
|
-
JSON.iconv('utf-8', 'utf-16be', b)
|
182
|
-
when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0
|
183
|
-
JSON.iconv('utf-8', 'utf-32le', b)
|
184
|
-
when b.size >= 4 && b[1] == 0 && b[3] == 0
|
185
|
-
JSON.iconv('utf-8', 'utf-16le', b)
|
186
|
-
else
|
187
|
-
b
|
188
|
-
end
|
189
141
|
end
|
190
142
|
source
|
191
143
|
end
|
@@ -245,7 +197,7 @@ module JSON
|
|
245
197
|
def parse_value
|
246
198
|
case
|
247
199
|
when scan(FLOAT)
|
248
|
-
Float(self[1])
|
200
|
+
@decimal_class && @decimal_class.new(self[1]) || Float(self[1])
|
249
201
|
when scan(INTEGER)
|
250
202
|
Integer(self[1])
|
251
203
|
when scan(TRUE)
|
@@ -254,7 +206,7 @@ module JSON
|
|
254
206
|
false
|
255
207
|
when scan(NULL)
|
256
208
|
nil
|
257
|
-
when (string = parse_string)
|
209
|
+
when !UNPARSED.equal?(string = parse_string)
|
258
210
|
string
|
259
211
|
when scan(ARRAY_OPEN)
|
260
212
|
@current_nesting += 1
|
@@ -284,7 +236,7 @@ module JSON
|
|
284
236
|
delim = false
|
285
237
|
until eos?
|
286
238
|
case
|
287
|
-
when (value = parse_value)
|
239
|
+
when !UNPARSED.equal?(value = parse_value)
|
288
240
|
delim = false
|
289
241
|
result << value
|
290
242
|
skip(IGNORE)
|
@@ -316,13 +268,13 @@ module JSON
|
|
316
268
|
delim = false
|
317
269
|
until eos?
|
318
270
|
case
|
319
|
-
when (string = parse_string)
|
271
|
+
when !UNPARSED.equal?(string = parse_string)
|
320
272
|
skip(IGNORE)
|
321
273
|
unless scan(PAIR_DELIMITER)
|
322
274
|
raise ParserError, "expected ':' in object at '#{peek(20)}'!"
|
323
275
|
end
|
324
276
|
skip(IGNORE)
|
325
|
-
unless (value = parse_value)
|
277
|
+
unless UNPARSED.equal?(value = parse_value)
|
326
278
|
result[@symbolize_names ? string.to_sym : string] = value
|
327
279
|
delim = false
|
328
280
|
skip(IGNORE)
|