json 1.7.0 → 2.3.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 +7 -0
- data/.gitignore +7 -0
- data/.travis.yml +18 -10
- data/{CHANGES → CHANGES.md} +217 -69
- data/Gemfile +11 -12
- data/{COPYING-json-jruby → LICENSE} +5 -6
- data/{README-json-jruby.markdown → README-json-jruby.md} +0 -0
- data/{README.rdoc → README.md} +188 -137
- data/Rakefile +52 -37
- data/VERSION +1 -1
- data/ext/json/ext/fbuffer/fbuffer.h +38 -7
- data/ext/json/ext/generator/depend +1 -0
- data/ext/json/ext/generator/extconf.rb +1 -10
- data/ext/json/ext/generator/generator.c +239 -133
- data/ext/json/ext/generator/generator.h +35 -26
- data/ext/json/ext/parser/depend +1 -0
- data/ext/json/ext/parser/extconf.rb +2 -9
- data/ext/json/ext/parser/parser.c +446 -514
- data/ext/json/ext/parser/parser.h +23 -9
- data/ext/json/ext/parser/parser.rl +177 -208
- data/ext/json/extconf.rb +2 -0
- data/java/src/json/ext/ByteListTranscoder.java +1 -2
- data/java/src/json/ext/Generator.java +49 -20
- 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 +25 -57
- data/java/src/json/ext/OptionsReader.java +5 -5
- data/java/src/json/ext/Parser.java +141 -419
- data/java/src/json/ext/Parser.rl +57 -128
- 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 +17 -2
- data/json.gemspec +0 -0
- data/json_pure.gemspec +25 -26
- data/lib/json.rb +3 -2
- data/lib/json/add/bigdecimal.rb +10 -2
- data/lib/json/add/complex.rb +9 -2
- 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 +8 -2
- data/lib/json/add/regexp.rb +3 -3
- 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 +6 -3
- data/lib/json/common.rb +51 -66
- data/lib/json/ext.rb +0 -6
- data/lib/json/generic_object.rb +36 -4
- data/lib/json/pure.rb +2 -8
- data/lib/json/pure/generator.rb +106 -119
- data/lib/json/pure/parser.rb +48 -88
- data/lib/json/version.rb +2 -1
- data/references/rfc7159.txt +899 -0
- data/tests/fixtures/fail18.json +1 -1
- data/tests/fixtures/obsolete_fail1.json +1 -0
- data/tests/{test_json_addition.rb → json_addition_test.rb} +53 -38
- 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/json_generator_test.rb +421 -0
- data/tests/json_generic_object_test.rb +82 -0
- 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 +49 -72
- data/COPYING +0 -58
- 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 -539
- data/tests/test_json_encoding.rb +0 -65
- data/tests/test_json_generate.rb +0 -251
- data/tests/test_json_generic_object.rb +0 -35
- data/tests/test_json_string_matching.rb +0 -40
- data/tests/test_json_unicode.rb +0 -72
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
|
@@ -5,24 +6,55 @@ module JSON
|
|
5
6
|
class << self
|
6
7
|
alias [] new
|
7
8
|
|
9
|
+
def json_creatable?
|
10
|
+
@json_creatable
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_writer :json_creatable
|
14
|
+
|
8
15
|
def json_create(data)
|
9
16
|
data = data.dup
|
10
17
|
data.delete JSON.create_id
|
11
18
|
self[data]
|
12
19
|
end
|
20
|
+
|
21
|
+
def from_hash(object)
|
22
|
+
case
|
23
|
+
when object.respond_to?(:to_hash)
|
24
|
+
result = new
|
25
|
+
object.to_hash.each do |key, value|
|
26
|
+
result[key] = from_hash(value)
|
27
|
+
end
|
28
|
+
result
|
29
|
+
when object.respond_to?(:to_ary)
|
30
|
+
object.to_ary.map { |a| from_hash(a) }
|
31
|
+
else
|
32
|
+
object
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def load(source, proc = nil, opts = {})
|
37
|
+
result = ::JSON.load(source, proc, opts.merge(:object_class => self))
|
38
|
+
result.nil? ? new : result
|
39
|
+
end
|
40
|
+
|
41
|
+
def dump(obj, *args)
|
42
|
+
::JSON.dump(obj, *args)
|
43
|
+
end
|
13
44
|
end
|
45
|
+
self.json_creatable = false
|
14
46
|
|
15
47
|
def to_hash
|
16
48
|
table
|
17
49
|
end
|
18
50
|
|
19
51
|
def [](name)
|
20
|
-
|
21
|
-
end
|
52
|
+
__send__(name)
|
53
|
+
end unless method_defined?(:[])
|
22
54
|
|
23
55
|
def []=(name, value)
|
24
|
-
__send__
|
25
|
-
end
|
56
|
+
__send__("#{name}=", value)
|
57
|
+
end unless method_defined?(:[]=)
|
26
58
|
|
27
59
|
def |(other)
|
28
60
|
self.class[other.to_hash.merge(to_hash)]
|
data/lib/json/pure.rb
CHANGED
@@ -1,17 +1,11 @@
|
|
1
|
-
if ENV['SIMPLECOV_COVERAGE'].to_i == 1
|
2
|
-
require 'simplecov'
|
3
|
-
SimpleCov.start do
|
4
|
-
add_filter "/tests/"
|
5
|
-
end
|
6
|
-
end
|
7
1
|
require 'json/common'
|
8
|
-
require 'json/pure/parser'
|
9
|
-
require 'json/pure/generator'
|
10
2
|
|
11
3
|
module JSON
|
12
4
|
# This module holds all the modules/classes that implement JSON's
|
13
5
|
# functionality in pure ruby.
|
14
6
|
module Pure
|
7
|
+
require 'json/pure/parser'
|
8
|
+
require 'json/pure/generator'
|
15
9
|
$DEBUG and warn "Using Pure library for JSON."
|
16
10
|
JSON.parser = Parser
|
17
11
|
JSON.generator = Generator
|
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,63 +39,44 @@ 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
|
-
string
|
49
|
-
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
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
def utf8_to_json(string) # :nodoc:
|
75
|
-
string.gsub(/["\\\x0-\x1f]/) { MAP[$&] }
|
76
|
-
end
|
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
|
77
73
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
[\xc2-\xdf][\x80-\xbf] |
|
83
|
-
[\xe0-\xef][\x80-\xbf]{2} |
|
84
|
-
[\xf0-\xf4][\x80-\xbf]{3}
|
85
|
-
)+ |
|
86
|
-
[\x80-\xc1\xf5-\xff] # invalid
|
87
|
-
)/nx) { |c|
|
88
|
-
c.size == 1 and raise GeneratorError, "invalid utf8 byte: '#{c}'"
|
89
|
-
s = JSON.iconv('utf-16be', 'utf-8', c).unpack('H*')[0]
|
90
|
-
s.gsub!(/.{4}/n, '\\\\u\&')
|
91
|
-
}
|
92
|
-
string
|
93
|
-
rescue => e
|
94
|
-
raise GeneratorError, "Caught #{e.class}: #{e}"
|
95
|
-
end
|
74
|
+
def valid_utf8?(string)
|
75
|
+
encoding = string.encoding
|
76
|
+
(encoding == Encoding::UTF_8 || encoding == Encoding::ASCII) &&
|
77
|
+
string.valid_encoding?
|
96
78
|
end
|
97
|
-
module_function :utf8_to_json, :utf8_to_json_ascii
|
79
|
+
module_function :utf8_to_json, :utf8_to_json_ascii, :valid_utf8?
|
98
80
|
|
99
81
|
module Pure
|
100
82
|
module Generator
|
@@ -133,8 +115,6 @@ module JSON
|
|
133
115
|
# * *allow_nan*: true if NaN, Infinity, and -Infinity should be
|
134
116
|
# generated, otherwise an exception is thrown, if these values are
|
135
117
|
# encountered. This options defaults to false.
|
136
|
-
# * *quirks_mode*: Enables quirks_mode for parser, that is for example
|
137
|
-
# generating single JSON values instead of documents is possible.
|
138
118
|
def initialize(opts = {})
|
139
119
|
@indent = ''
|
140
120
|
@space = ''
|
@@ -143,7 +123,6 @@ module JSON
|
|
143
123
|
@array_nl = ''
|
144
124
|
@allow_nan = false
|
145
125
|
@ascii_only = false
|
146
|
-
@quirks_mode = false
|
147
126
|
@buffer_initial_length = 1024
|
148
127
|
configure opts
|
149
128
|
end
|
@@ -169,10 +148,6 @@ module JSON
|
|
169
148
|
# the generated JSON, max_nesting = 0 if no maximum is checked.
|
170
149
|
attr_accessor :max_nesting
|
171
150
|
|
172
|
-
# If this attribute is set to true, quirks mode is enabled, otherwise
|
173
|
-
# it's disabled.
|
174
|
-
attr_accessor :quirks_mode
|
175
|
-
|
176
151
|
# :stopdoc:
|
177
152
|
attr_reader :buffer_initial_length
|
178
153
|
|
@@ -212,25 +187,31 @@ module JSON
|
|
212
187
|
@ascii_only
|
213
188
|
end
|
214
189
|
|
215
|
-
# Returns true, if quirks mode is enabled. Otherwise returns false.
|
216
|
-
def quirks_mode?
|
217
|
-
@quirks_mode
|
218
|
-
end
|
219
|
-
|
220
190
|
# Configure this State instance with the Hash _opts_, and return
|
221
191
|
# itself.
|
222
192
|
def configure(opts)
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
193
|
+
if opts.respond_to?(:to_hash)
|
194
|
+
opts = opts.to_hash
|
195
|
+
elsif opts.respond_to?(:to_h)
|
196
|
+
opts = opts.to_h
|
197
|
+
else
|
198
|
+
raise TypeError, "can't convert #{opts.class} into Hash"
|
199
|
+
end
|
200
|
+
for key, value in opts
|
201
|
+
instance_variable_set "@#{key}", value
|
202
|
+
end
|
203
|
+
@indent = opts[:indent] if opts.key?(:indent)
|
204
|
+
@space = opts[:space] if opts.key?(:space)
|
205
|
+
@space_before = opts[:space_before] if opts.key?(:space_before)
|
206
|
+
@object_nl = opts[:object_nl] if opts.key?(:object_nl)
|
207
|
+
@array_nl = opts[:array_nl] if opts.key?(:array_nl)
|
208
|
+
@allow_nan = !!opts[:allow_nan] if opts.key?(:allow_nan)
|
209
|
+
@ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
|
210
|
+
@depth = opts[:depth] || 0
|
211
|
+
@buffer_initial_length ||= opts[:buffer_initial_length]
|
212
|
+
|
213
|
+
if !opts.key?(:max_nesting) # defaults to 100
|
214
|
+
@max_nesting = 100
|
234
215
|
elsif opts[:max_nesting]
|
235
216
|
@max_nesting = opts[:max_nesting]
|
236
217
|
else
|
@@ -244,30 +225,42 @@ module JSON
|
|
244
225
|
# passed to the configure method.
|
245
226
|
def to_h
|
246
227
|
result = {}
|
247
|
-
for iv in
|
248
|
-
|
228
|
+
for iv in instance_variables
|
229
|
+
iv = iv.to_s[1..-1]
|
230
|
+
result[iv.to_sym] = self[iv]
|
249
231
|
end
|
250
232
|
result
|
251
233
|
end
|
252
234
|
|
253
|
-
|
254
|
-
|
235
|
+
alias to_hash to_h
|
236
|
+
|
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
|
255
240
|
# GeneratorError exception.
|
256
241
|
def generate(obj)
|
257
242
|
result = obj.to_json(self)
|
258
|
-
|
259
|
-
|
260
|
-
result =~ /\A\s*\{/ && result =~ /\}\s*\Z/
|
261
|
-
then
|
262
|
-
raise GeneratorError, "only generation of JSON objects or arrays allowed"
|
263
|
-
end
|
264
|
-
end
|
243
|
+
JSON.valid_utf8?(result) or raise GeneratorError,
|
244
|
+
"source sequence #{result.inspect} is illegal/malformed utf-8"
|
265
245
|
result
|
266
246
|
end
|
267
247
|
|
268
248
|
# Return the value returned by method +name+.
|
269
249
|
def [](name)
|
270
|
-
|
250
|
+
if respond_to?(name)
|
251
|
+
__send__(name)
|
252
|
+
else
|
253
|
+
instance_variable_get("@#{name}") if
|
254
|
+
instance_variables.include?("@#{name}".to_sym) # avoid warning
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def []=(name, value)
|
259
|
+
if respond_to?(name_writer = "#{name}=")
|
260
|
+
__send__ name_writer, value
|
261
|
+
else
|
262
|
+
instance_variable_set "@#{name}", value
|
263
|
+
end
|
271
264
|
end
|
272
265
|
end
|
273
266
|
|
@@ -313,12 +306,16 @@ module JSON
|
|
313
306
|
result << state.space_before
|
314
307
|
result << ':'
|
315
308
|
result << state.space
|
316
|
-
|
309
|
+
if value.respond_to?(:to_json)
|
310
|
+
result << value.to_json(state)
|
311
|
+
else
|
312
|
+
result << %{"#{String(value)}"}
|
313
|
+
end
|
317
314
|
first = false
|
318
315
|
}
|
319
316
|
depth = state.depth -= 1
|
320
317
|
result << state.object_nl
|
321
|
-
result << state.indent * depth if indent
|
318
|
+
result << state.indent * depth if indent
|
322
319
|
result << '}'
|
323
320
|
result
|
324
321
|
end
|
@@ -348,7 +345,11 @@ module JSON
|
|
348
345
|
each { |value|
|
349
346
|
result << delim unless first
|
350
347
|
result << state.indent * depth if indent
|
351
|
-
|
348
|
+
if value.respond_to?(:to_json)
|
349
|
+
result << value.to_json(state)
|
350
|
+
else
|
351
|
+
result << %{"#{String(value)}"}
|
352
|
+
end
|
352
353
|
first = false
|
353
354
|
}
|
354
355
|
depth = state.depth -= 1
|
@@ -387,34 +388,20 @@ module JSON
|
|
387
388
|
end
|
388
389
|
|
389
390
|
module String
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
string = encode(::Encoding::UTF_8)
|
400
|
-
end
|
401
|
-
if state.ascii_only?
|
402
|
-
'"' << JSON.utf8_to_json_ascii(string) << '"'
|
403
|
-
else
|
404
|
-
'"' << JSON.utf8_to_json(string) << '"'
|
405
|
-
end
|
391
|
+
# This string should be encoded with UTF-8 A call to this method
|
392
|
+
# returns a JSON string encoded with UTF16 big endian characters as
|
393
|
+
# \u????.
|
394
|
+
def to_json(state = nil, *args)
|
395
|
+
state = State.from_state(state)
|
396
|
+
if encoding == ::Encoding::UTF_8
|
397
|
+
string = self
|
398
|
+
else
|
399
|
+
string = encode(::Encoding::UTF_8)
|
406
400
|
end
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
def to_json(state = nil, *args)
|
412
|
-
state = State.from_state(state)
|
413
|
-
if state.ascii_only?
|
414
|
-
'"' << JSON.utf8_to_json_ascii(self) << '"'
|
415
|
-
else
|
416
|
-
'"' << JSON.utf8_to_json(self) << '"'
|
417
|
-
end
|
401
|
+
if state.ascii_only?
|
402
|
+
'"' << JSON.utf8_to_json_ascii(string) << '"'
|
403
|
+
else
|
404
|
+
'"' << JSON.utf8_to_json(string) << '"'
|
418
405
|
end
|
419
406
|
end
|
420
407
|
|
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
|
#
|
@@ -56,28 +57,28 @@ module JSON
|
|
56
57
|
# keys:
|
57
58
|
# * *max_nesting*: The maximum depth of nesting allowed in the parsed data
|
58
59
|
# structures. Disable depth checking with :max_nesting => false|nil|0,
|
59
|
-
# it defaults to
|
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.
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
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.
|
68
|
+
# * *create_additions*: If set to true, the Parser creates
|
69
|
+
# additions when if a matching class and create_id was found. This
|
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
|
-
if !opts.key?(:max_nesting) # defaults to
|
80
|
-
@max_nesting =
|
80
|
+
if !opts.key?(:max_nesting) # defaults to 100
|
81
|
+
@max_nesting = 100
|
81
82
|
elsif opts[:max_nesting]
|
82
83
|
@max_nesting = opts[:max_nesting]
|
83
84
|
else
|
@@ -88,58 +89,40 @@ module JSON
|
|
88
89
|
if opts.key?(:create_additions)
|
89
90
|
@create_additions = !!opts[:create_additions]
|
90
91
|
else
|
91
|
-
@create_additions =
|
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,15 @@ module JSON
|
|
245
197
|
def parse_value
|
246
198
|
case
|
247
199
|
when scan(FLOAT)
|
248
|
-
|
200
|
+
if @decimal_class then
|
201
|
+
if @decimal_class == BigDecimal then
|
202
|
+
BigDecimal(self[1])
|
203
|
+
else
|
204
|
+
@decimal_class.new(self[1]) || Float(self[1])
|
205
|
+
end
|
206
|
+
else
|
207
|
+
Float(self[1])
|
208
|
+
end
|
249
209
|
when scan(INTEGER)
|
250
210
|
Integer(self[1])
|
251
211
|
when scan(TRUE)
|
@@ -254,7 +214,7 @@ module JSON
|
|
254
214
|
false
|
255
215
|
when scan(NULL)
|
256
216
|
nil
|
257
|
-
when (string = parse_string)
|
217
|
+
when !UNPARSED.equal?(string = parse_string)
|
258
218
|
string
|
259
219
|
when scan(ARRAY_OPEN)
|
260
220
|
@current_nesting += 1
|
@@ -284,7 +244,7 @@ module JSON
|
|
284
244
|
delim = false
|
285
245
|
until eos?
|
286
246
|
case
|
287
|
-
when (value = parse_value)
|
247
|
+
when !UNPARSED.equal?(value = parse_value)
|
288
248
|
delim = false
|
289
249
|
result << value
|
290
250
|
skip(IGNORE)
|
@@ -316,13 +276,13 @@ module JSON
|
|
316
276
|
delim = false
|
317
277
|
until eos?
|
318
278
|
case
|
319
|
-
when (string = parse_string)
|
279
|
+
when !UNPARSED.equal?(string = parse_string)
|
320
280
|
skip(IGNORE)
|
321
281
|
unless scan(PAIR_DELIMITER)
|
322
282
|
raise ParserError, "expected ':' in object at '#{peek(20)}'!"
|
323
283
|
end
|
324
284
|
skip(IGNORE)
|
325
|
-
unless (value = parse_value)
|
285
|
+
unless UNPARSED.equal?(value = parse_value)
|
326
286
|
result[@symbolize_names ? string.to_sym : string] = value
|
327
287
|
delim = false
|
328
288
|
skip(IGNORE)
|