json 2.3.1-java → 2.4.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dab6c5a90b48e148a0987ce6cf13284c517b672bf9eedc6672b9b0cfb7123af5
4
- data.tar.gz: 2668c1bbb2ece7579896373029a947671894b8882072cc5cc56908210a5973cb
3
+ metadata.gz: 4b0ed6ed8147c1e99dd585403ea77d2ddfe044b2039ebdeea1226fdbf39459fa
4
+ data.tar.gz: f3c2584779ff507b86dd9df78dcc2ae9fe4b1904952db719985327609896108e
5
5
  SHA512:
6
- metadata.gz: '0715338d655adec7af365f721ac56a2737436f8771a002cb303f86b7b800717378e84e9401a09a5ab7de1a4116d3891ad15ad8aa598747296004d55adb2ff2bd'
7
- data.tar.gz: c1b6446ef0b012974aed4595de272179109a28ce890e6459f39e991b2ed10b5e0997cb37c03a32bf84ba634b6347d80e8144afa7e2771b60e458f36beac8ee53
6
+ metadata.gz: bf55f870a11035a308017c8d8555335f410ba7780c419926e0a334ef3ed475027ea2eb12408cf1eceab347e77960127516667f8aa50c9549032e593da6de0a5e
7
+ data.tar.gz: a25e1338acfc66cec81e6e27f130f85c178b5962bc7a9b153c479001ec72cc23fb6ae5ac80299bbefad30cec89b90b73906e758253cdf91dca1041a135b1d5e1
data/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
@@ -107,6 +107,89 @@ require 'json/common'
107
107
  # ruby # => nil
108
108
  # ruby.class # => NilClass
109
109
  #
110
+ # ==== Parsing Options
111
+ #
112
+ # ====== Input Options
113
+ #
114
+ # Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed;
115
+ # defaults to +100+; specify +false+ to disable depth checking.
116
+ #
117
+ # With the default, +false+:
118
+ # source = '[0, [1, [2, [3]]]]'
119
+ # ruby = JSON.parse(source)
120
+ # ruby # => [0, [1, [2, [3]]]]
121
+ # Too deep:
122
+ # # Raises JSON::NestingError (nesting of 2 is too deep):
123
+ # JSON.parse(source, {max_nesting: 1})
124
+ # Bad value:
125
+ # # Raises TypeError (wrong argument type Symbol (expected Fixnum)):
126
+ # JSON.parse(source, {max_nesting: :foo})
127
+ #
128
+ # ---
129
+ #
130
+ # Option +allow_nan+ (boolean) specifies whether to allow
131
+ # NaN, Infinity, and MinusInfinity in +source+;
132
+ # defaults to +false+.
133
+ #
134
+ # With the default, +false+:
135
+ # # Raises JSON::ParserError (225: unexpected token at '[NaN]'):
136
+ # JSON.parse('[NaN]')
137
+ # # Raises JSON::ParserError (232: unexpected token at '[Infinity]'):
138
+ # JSON.parse('[Infinity]')
139
+ # # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'):
140
+ # JSON.parse('[-Infinity]')
141
+ # Allow:
142
+ # source = '[NaN, Infinity, -Infinity]'
143
+ # ruby = JSON.parse(source, {allow_nan: true})
144
+ # ruby # => [NaN, Infinity, -Infinity]
145
+ #
146
+ # ====== Output Options
147
+ #
148
+ # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
149
+ # should be Symbols;
150
+ # defaults to +false+ (use Strings).
151
+ #
152
+ # With the default, +false+:
153
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
154
+ # ruby = JSON.parse(source)
155
+ # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
156
+ # Use Symbols:
157
+ # ruby = JSON.parse(source, {symbolize_names: true})
158
+ # ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
159
+ #
160
+ # ---
161
+ #
162
+ # Option +object_class+ (\Class) specifies the Ruby class to be used
163
+ # for each \JSON object;
164
+ # defaults to \Hash.
165
+ #
166
+ # With the default, \Hash:
167
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
168
+ # ruby = JSON.parse(source)
169
+ # ruby.class # => Hash
170
+ # Use class \OpenStruct:
171
+ # ruby = JSON.parse(source, {object_class: OpenStruct})
172
+ # ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
173
+ #
174
+ # ---
175
+ #
176
+ # Option +array_class+ (\Class) specifies the Ruby class to be used
177
+ # for each \JSON array;
178
+ # defaults to \Array.
179
+ #
180
+ # With the default, \Array:
181
+ # source = '["foo", 1.0, true, false, null]'
182
+ # ruby = JSON.parse(source)
183
+ # ruby.class # => Array
184
+ # Use class \Set:
185
+ # ruby = JSON.parse(source, {array_class: Set})
186
+ # ruby # => #<Set: {"foo", 1.0, true, false, nil}>
187
+ #
188
+ # ---
189
+ #
190
+ # Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
191
+ # See {\JSON Additions}[#module-JSON-label-JSON+Additions].
192
+ #
110
193
  # === Generating \JSON
111
194
  #
112
195
  # To generate a Ruby \String containing \JSON data,
@@ -169,6 +252,94 @@ require 'json/common'
169
252
  # JSON.generate(Complex(0, 0)) # => '"0+0i"'
170
253
  # JSON.generate(Dir.new('.')) # => '"#<Dir>"'
171
254
  #
255
+ # ==== Generating Options
256
+ #
257
+ # ====== Input Options
258
+ #
259
+ # Option +allow_nan+ (boolean) specifies whether
260
+ # +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
261
+ # defaults to +false+.
262
+ #
263
+ # With the default, +false+:
264
+ # # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
265
+ # JSON.generate(JSON::NaN)
266
+ # # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
267
+ # JSON.generate(JSON::Infinity)
268
+ # # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
269
+ # JSON.generate(JSON::MinusInfinity)
270
+ #
271
+ # Allow:
272
+ # ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity]
273
+ # JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
274
+ #
275
+ # ---
276
+ #
277
+ # Option +max_nesting+ (\Integer) specifies the maximum nesting depth
278
+ # in +obj+; defaults to +100+.
279
+ #
280
+ # With the default, +100+:
281
+ # obj = [[[[[[0]]]]]]
282
+ # JSON.generate(obj) # => '[[[[[[0]]]]]]'
283
+ #
284
+ # Too deep:
285
+ # # Raises JSON::NestingError (nesting of 2 is too deep):
286
+ # JSON.generate(obj, max_nesting: 2)
287
+ #
288
+ # ====== Output Options
289
+ #
290
+ # The default formatting options generate the most compact
291
+ # \JSON data, all on one line and with no whitespace.
292
+ #
293
+ # You can use these formatting options to generate
294
+ # \JSON data in a more open format, using whitespace.
295
+ # See also JSON.pretty_generate.
296
+ #
297
+ # - Option +array_nl+ (\String) specifies a string (usually a newline)
298
+ # to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
299
+ # - Option +object_nl+ (\String) specifies a string (usually a newline)
300
+ # to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
301
+ # - Option +indent+ (\String) specifies the string (usually spaces) to be
302
+ # used for indentation; defaults to the empty \String, <tt>''</tt>;
303
+ # defaults to the empty \String, <tt>''</tt>;
304
+ # has no effect unless options +array_nl+ or +object_nl+ specify newlines.
305
+ # - Option +space+ (\String) specifies a string (usually a space) to be
306
+ # inserted after the colon in each \JSON object's pair;
307
+ # defaults to the empty \String, <tt>''</tt>.
308
+ # - Option +space_before+ (\String) specifies a string (usually a space) to be
309
+ # inserted before the colon in each \JSON object's pair;
310
+ # defaults to the empty \String, <tt>''</tt>.
311
+ #
312
+ # In this example, +obj+ is used first to generate the shortest
313
+ # \JSON data (no whitespace), then again with all formatting options
314
+ # specified:
315
+ #
316
+ # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
317
+ # json = JSON.generate(obj)
318
+ # puts 'Compact:', json
319
+ # opts = {
320
+ # array_nl: "\n",
321
+ # object_nl: "\n",
322
+ # indent: ' ',
323
+ # space_before: ' ',
324
+ # space: ' '
325
+ # }
326
+ # puts 'Open:', JSON.generate(obj, opts)
327
+ #
328
+ # Output:
329
+ # Compact:
330
+ # {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
331
+ # Open:
332
+ # {
333
+ # "foo" : [
334
+ # "bar",
335
+ # "baz"
336
+ # ],
337
+ # "bat" : {
338
+ # "bam" : 0,
339
+ # "bad" : 1
340
+ # }
341
+ # }
342
+ #
172
343
  # == \JSON Additions
173
344
  #
174
345
  # When you "round trip" a non-\String object from Ruby to \JSON and back,
@@ -2,7 +2,6 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- defined?(::Complex) or require 'complex'
6
5
 
7
6
  class Complex
8
7
 
@@ -2,7 +2,6 @@
2
2
  unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
3
3
  require 'json'
4
4
  end
5
- defined?(::Rational) or require 'rational'
6
5
 
7
6
  class Rational
8
7
  # Deserializes JSON string by converting numerator value <tt>n</tt>,
@@ -4,13 +4,15 @@ require 'json/generic_object'
4
4
 
5
5
  module JSON
6
6
  class << self
7
- # If +object+ is a
8
- # {String-convertible object}[doc/implicit_conversion_rdoc.html#label-String-Convertible+Objects]
9
- # (implementing +to_str+), calls JSON.parse with +object+ and +opts+:
7
+ # :call-seq:
8
+ # JSON[object] -> new_array or new_string
9
+ #
10
+ # If +object+ is a \String,
11
+ # calls JSON.parse with +object+ and +opts+ (see method #parse):
10
12
  # json = '[0, 1, null]'
11
13
  # JSON[json]# => [0, 1, nil]
12
14
  #
13
- # Otherwise, calls JSON.generate with +object+ and +opts+:
15
+ # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
14
16
  # ruby = [0, 1, nil]
15
17
  # JSON[ruby] # => '[0,1,null]'
16
18
  def [](object, opts = {})
@@ -144,15 +146,12 @@ module JSON
144
146
  # :call-seq:
145
147
  # JSON.parse(source, opts) -> object
146
148
  #
147
- # Argument +source+ contains the \String to be parsed. It must be a
148
- # {String-convertible object}[doc/implicit_conversion_rdoc.html#label-String-Convertible+Objects]
149
- # (implementing +to_str+), and must contain valid \JSON data.
149
+ # Returns the Ruby objects created by parsing the given +source+.
150
150
  #
151
- # Argument +opts+, if given, contains options for the parsing, and must be a
152
- # {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects]
153
- # (implementing +to_hash+).
151
+ # Argument +source+ contains the \String to be parsed.
154
152
  #
155
- # Returns the Ruby objects created by parsing the given +source+.
153
+ # Argument +opts+, if given, contains a \Hash of options for the parsing.
154
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
156
155
  #
157
156
  # ---
158
157
  #
@@ -171,91 +170,24 @@ module JSON
171
170
  # For examples of parsing for all \JSON data types, see
172
171
  # {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
173
172
  #
174
- # ====== Input Options
175
- #
176
- # Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed;
177
- # defaults to +100+; specify +false+ to disable depth checking.
178
- #
179
- # With the default, +false+:
180
- # source = '[0, [1, [2, [3]]]]'
181
- # ruby = JSON.parse(source)
182
- # ruby # => [0, [1, [2, [3]]]]
183
- # Too deep:
184
- # # Raises JSON::NestingError (nesting of 2 is too deep):
185
- # JSON.parse(source, {max_nesting: 1})
186
- # Bad value:
187
- # # Raises TypeError (wrong argument type Symbol (expected Fixnum)):
188
- # JSON.parse(source, {max_nesting: :foo})
189
- #
190
- # ---
191
- #
192
- # Option +allow_nan+ (boolean) specifies whether to allow
193
- # NaN, Infinity, and MinusInfinity in +source+;
194
- # defaults to +false+.
195
- #
196
- # With the default, +false+:
197
- # # Raises JSON::ParserError (225: unexpected token at '[NaN]'):
198
- # JSON.parse('[NaN]')
199
- # # Raises JSON::ParserError (232: unexpected token at '[Infinity]'):
200
- # JSON.parse('[Infinity]')
201
- # # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'):
202
- # JSON.parse('[-Infinity]')
203
- # Allow:
204
- # source = '[NaN, Infinity, -Infinity]'
205
- # ruby = JSON.parse(source, {allow_nan: true})
206
- # ruby # => [NaN, Infinity, -Infinity]
207
- #
208
- # ====== Output Options
209
- #
210
- # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
211
- # should be Symbols;
212
- # defaults to +false+ (use Strings).
213
- #
214
- # With the default, +false+:
215
- # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
216
- # ruby = JSON.parse(source)
217
- # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
218
- # Use Symbols:
219
- # ruby = JSON.parse(source, {symbolize_names: true})
220
- # ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
221
- #
222
- # ---
223
- #
224
- # Option +object_class+ (\Class) specifies the Ruby class to be used
225
- # for each \JSON object;
226
- # defaults to \Hash.
227
- #
228
- # With the default, \Hash:
229
- # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
230
- # ruby = JSON.parse(source)
231
- # ruby.class # => Hash
232
- # Use class \OpenStruct:
233
- # ruby = JSON.parse(source, {object_class: OpenStruct})
234
- # ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
235
- #
236
- # ---
237
- #
238
- # Option +array_class+ (\Class) specifies the Ruby class to be used
239
- # for each \JSON array;
240
- # defaults to \Array.
241
- #
242
- # With the default, \Array:
243
- # source = '["foo", 1.0, true, false, null]'
173
+ # Parses nested JSON objects:
174
+ # source = <<-EOT
175
+ # {
176
+ # "name": "Dave",
177
+ # "age" :40,
178
+ # "hats": [
179
+ # "Cattleman's",
180
+ # "Panama",
181
+ # "Tophat"
182
+ # ]
183
+ # }
184
+ # EOT
244
185
  # ruby = JSON.parse(source)
245
- # ruby.class # => Array
246
- # Use class \Set:
247
- # ruby = JSON.parse(source, {array_class: Set})
248
- # ruby # => #<Set: {"foo", 1.0, true, false, nil}>
186
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
249
187
  #
250
188
  # ---
251
189
  #
252
- # Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
253
- # See {\JSON Additions}[#module-JSON-label-JSON+Additions].
254
- #
255
- # ====== Exceptions
256
- #
257
190
  # Raises an exception if +source+ is not valid JSON:
258
- #
259
191
  # # Raises JSON::ParserError (783: unexpected token at ''):
260
192
  # JSON.parse('')
261
193
  #
@@ -283,30 +215,47 @@ module JSON
283
215
  end
284
216
 
285
217
  # :call-seq:
286
- # JSON.generate(obj, opts = nil) -> new_string
218
+ # JSON.load_file(path, opts={}) -> object
287
219
  #
288
- # Argument +obj+ is the Ruby object to be converted to \JSON.
220
+ # Calls:
221
+ # parse(File.read(path), opts)
289
222
  #
290
- # Argument +opts+, if given, contains options for the generation, and must be a
291
- # {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects]
292
- # (implementing +to_hash+).
223
+ # See method #parse.
224
+ def load_file(filespec, opts = {})
225
+ parse(File.read(filespec), opts)
226
+ end
227
+
228
+ # :call-seq:
229
+ # JSON.load_file!(path, opts = {})
230
+ #
231
+ # Calls:
232
+ # JSON.parse!(File.read(path, opts))
233
+ #
234
+ # See method #parse!
235
+ def load_file!(filespec, opts = {})
236
+ parse!(File.read(filespec), opts)
237
+ end
238
+
239
+ # :call-seq:
240
+ # JSON.generate(obj, opts = nil) -> new_string
293
241
  #
294
242
  # Returns a \String containing the generated \JSON data.
295
243
  #
296
244
  # See also JSON.fast_generate, JSON.pretty_generate.
297
245
  #
246
+ # Argument +obj+ is the Ruby object to be converted to \JSON.
247
+ #
248
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
249
+ # See {Generating Options}[#module-JSON-label-Generating+Options].
250
+ #
298
251
  # ---
299
252
  #
300
- # When +obj+ is an
301
- # {Array-convertible object}[doc/implicit_conversion_rdoc.html#label-Array-Convertible+Objects]
302
- # (implementing +to_ary+), returns a \String containing a \JSON array:
253
+ # When +obj+ is an \Array, returns a \String containing a \JSON array:
303
254
  # obj = ["foo", 1.0, true, false, nil]
304
255
  # json = JSON.generate(obj)
305
256
  # json # => '["foo",1.0,true,false,null]'
306
257
  #
307
- # When +obj+ is a
308
- # {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects],
309
- # return a \String containing a \JSON object:
258
+ # When +obj+ is a \Hash, returns a \String containing a \JSON object:
310
259
  # obj = {foo: 0, bar: 's', baz: :bat}
311
260
  # json = JSON.generate(obj)
312
261
  # json # => '{"foo":0,"bar":"s","baz":"bat"}'
@@ -314,98 +263,10 @@ module JSON
314
263
  # For examples of generating from other Ruby objects, see
315
264
  # {Generating \JSON from Other Objects}[#module-JSON-label-Generating+JSON+from+Other+Objects].
316
265
  #
317
- # ====== Input Options
318
- #
319
- # Option +allow_nan+ (boolean) specifies whether
320
- # +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
321
- # defaults to +false+.
322
- #
323
- # With the default, +false+:
324
- # # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
325
- # JSON.generate(JSON::NaN)
326
- # # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
327
- # JSON.generate(JSON::Infinity)
328
- # # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
329
- # JSON.generate(JSON::MinusInfinity)
330
- #
331
- # Allow:
332
- # ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity]
333
- # JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
334
- #
335
- # ---
336
- #
337
- # Option +max_nesting+ (\Integer) specifies the maximum nesting depth
338
- # in +obj+; defaults to +100+.
339
- #
340
- # With the default, +100+:
341
- # obj = [[[[[[0]]]]]]
342
- # JSON.generate(obj) # => '[[[[[[0]]]]]]'
343
- #
344
- # Too deep:
345
- # # Raises JSON::NestingError (nesting of 2 is too deep):
346
- # JSON.generate(obj, max_nesting: 2)
347
- #
348
- # ====== Output Options
349
- #
350
- # The default formatting options generate the most compact
351
- # \JSON data, all on one line and with no whitespace.
352
- #
353
- # You can use these formatting options to generate
354
- # \JSON data in a more open format, using whitespace.
355
- # See also JSON.pretty_generate.
356
- #
357
- # - Option +array_nl+ (\String) specifies a string (usually a newline)
358
- # to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
359
- # - Option +object_nl+ (\String) specifies a string (usually a newline)
360
- # to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
361
- # - Option +indent+ (\String) specifies the string (usually spaces) to be
362
- # used for indentation; defaults to the empty \String, <tt>''</tt>;
363
- # defaults to the empty \String, <tt>''</tt>;
364
- # has no effect unless options +array_nl+ or +object_nl+ specify newlines.
365
- # - Option +space+ (\String) specifies a string (usually a space) to be
366
- # inserted after the colon in each \JSON object's pair;
367
- # defaults to the empty \String, <tt>''</tt>.
368
- # - Option +space_before+ (\String) specifies a string (usually a space) to be
369
- # inserted before the colon in each \JSON object's pair;
370
- # defaults to the empty \String, <tt>''</tt>.
371
- #
372
- # In this example, +obj+ is used first to generate the shortest
373
- # \JSON data (no whitespace), then again with all formatting options
374
- # specified:
375
- #
376
- # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
377
- # json = JSON.generate(obj)
378
- # puts 'Compact:', json
379
- # opts = {
380
- # array_nl: "\n",
381
- # object_nl: "\n",
382
- # indent+: ' ',
383
- # space_before: ' ',
384
- # space: ' '
385
- # }
386
- # puts 'Open:', JSON.generate(obj, opts)
387
- #
388
- # Output:
389
- # Compact:
390
- # {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
391
- # Open:
392
- # {
393
- # "foo" : [
394
- # "bar",
395
- # "baz"
396
- # ],
397
- # "bat" : {
398
- # "bam" : 0,
399
- # "bad" : 1
400
- # }
401
- # }
402
- #
403
266
  # ---
404
267
  #
405
268
  # Raises an exception if any formatting option is not a \String.
406
269
  #
407
- # ====== Exceptions
408
- #
409
270
  # Raises an exception if +obj+ contains circular references:
410
271
  # a = []; b = []; a.push(b); b.push(a)
411
272
  # # Raises JSON::NestingError (nesting of 100 is too deep):
@@ -437,6 +298,9 @@ module JSON
437
298
  module_function :unparse
438
299
  # :startdoc:
439
300
 
301
+ # :call-seq:
302
+ # JSON.fast_generate(obj, opts) -> new_string
303
+ #
440
304
  # Arguments +obj+ and +opts+ here are the same as
441
305
  # arguments +obj+ and +opts+ in JSON.generate.
442
306
  #
@@ -541,20 +405,134 @@ module JSON
541
405
  :create_additions => true,
542
406
  }
543
407
 
544
- # Load a ruby data structure from a JSON _source_ and return it. A source can
545
- # either be a string-like object, an IO-like object, or an object responding
546
- # to the read method. If _proc_ was given, it will be called with any nested
547
- # Ruby object as an argument recursively in depth first order. To modify the
548
- # default options pass in the optional _options_ argument as well.
408
+ # :call-seq:
409
+ # JSON.load(source, proc = nil, options = {}) -> object
549
410
  #
550
- # BEWARE: This method is meant to serialise data from trusted user input,
551
- # like from your own database server or clients under your control, it could
552
- # be dangerous to allow untrusted users to pass JSON sources into it. The
553
- # default options for the parser can be changed via the load_default_options
554
- # method.
411
+ # Returns the Ruby objects created by parsing the given +source+.
412
+ #
413
+ # - Argument +source+ must be, or be convertible to, a \String:
414
+ # - If +source+ responds to instance method +to_str+,
415
+ # <tt>source.to_str</tt> becomes the source.
416
+ # - If +source+ responds to instance method +to_io+,
417
+ # <tt>source.to_io.read</tt> becomes the source.
418
+ # - If +source+ responds to instance method +read+,
419
+ # <tt>source.read</tt> becomes the source.
420
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
421
+ # - Option +allow_blank+ specifies a truthy value.
422
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
423
+ # - Otherwise, +source+ remains the source.
424
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
425
+ # It will be called recursively with each result (depth-first order).
426
+ # See details below.
427
+ # BEWARE: This method is meant to serialise data from trusted user input,
428
+ # like from your own database server or clients under your control, it could
429
+ # be dangerous to allow untrusted users to pass JSON sources into it.
430
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
431
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
432
+ # The default options can be changed via method JSON.load_default_options=.
433
+ #
434
+ # ---
435
+ #
436
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
437
+ # <tt>parse(source, opts)</tt>; see #parse.
438
+ #
439
+ # Source for following examples:
440
+ # source = <<-EOT
441
+ # {
442
+ # "name": "Dave",
443
+ # "age" :40,
444
+ # "hats": [
445
+ # "Cattleman's",
446
+ # "Panama",
447
+ # "Tophat"
448
+ # ]
449
+ # }
450
+ # EOT
451
+ #
452
+ # Load a \String:
453
+ # ruby = JSON.load(source)
454
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
455
+ #
456
+ # Load an \IO object:
457
+ # require 'stringio'
458
+ # object = JSON.load(StringIO.new(source))
459
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
460
+ #
461
+ # Load a \File object:
462
+ # path = 't.json'
463
+ # File.write(path, source)
464
+ # File.open(path) do |file|
465
+ # JSON.load(file)
466
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
467
+ #
468
+ # ---
469
+ #
470
+ # When +proc+ is given:
471
+ # - Modifies +source+ as above.
472
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
473
+ # - Recursively calls <tt>proc(result)</tt>.
474
+ # - Returns the final result.
475
+ #
476
+ # Example:
477
+ # require 'json'
478
+ #
479
+ # # Some classes for the example.
480
+ # class Base
481
+ # def initialize(attributes)
482
+ # @attributes = attributes
483
+ # end
484
+ # end
485
+ # class User < Base; end
486
+ # class Account < Base; end
487
+ # class Admin < Base; end
488
+ # # The JSON source.
489
+ # json = <<-EOF
490
+ # {
491
+ # "users": [
492
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
493
+ # {"type": "User", "username": "john", "email": "john@example.com"}
494
+ # ],
495
+ # "accounts": [
496
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
497
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
498
+ # ],
499
+ # "admins": {"type": "Admin", "password": "0wn3d"}
500
+ # }
501
+ # EOF
502
+ # # Deserializer method.
503
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
504
+ # type = obj.is_a?(Hash) && obj["type"]
505
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
506
+ # end
507
+ # # Call to JSON.load
508
+ # ruby = JSON.load(json, proc {|obj|
509
+ # case obj
510
+ # when Hash
511
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
512
+ # when Array
513
+ # obj.map! {|v| deserialize_obj v }
514
+ # end
515
+ # })
516
+ # pp ruby
517
+ # Output:
518
+ # {"users"=>
519
+ # [#<User:0x00000000064c4c98
520
+ # @attributes=
521
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
522
+ # #<User:0x00000000064c4bd0
523
+ # @attributes=
524
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
525
+ # "accounts"=>
526
+ # [{"account"=>
527
+ # #<Account:0x00000000064c4928
528
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
529
+ # {"account"=>
530
+ # #<Account:0x00000000064c4680
531
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
532
+ # "admins"=>
533
+ # #<Admin:0x00000000064c41f8
534
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
555
535
  #
556
- # This method is part of the implementation of the load/dump interface of
557
- # Marshal and YAML.
558
536
  def load(source, proc = nil, options = {})
559
537
  opts = load_default_options.merge options
560
538
  if source.respond_to? :to_str
@@ -573,7 +551,7 @@ module JSON
573
551
  end
574
552
 
575
553
  # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
576
- def recurse_proc(result, &proc)
554
+ def recurse_proc(result, &proc) # :nodoc:
577
555
  case result
578
556
  when Array
579
557
  result.each { |x| recurse_proc x, &proc }
@@ -593,29 +571,42 @@ module JSON
593
571
  # Sets or returns the default options for the JSON.dump method.
594
572
  # Initially:
595
573
  # opts = JSON.dump_default_options
596
- # opts # => {:max_nesting=>false, :allow_nan=>true}
574
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
597
575
  attr_accessor :dump_default_options
598
576
  end
599
577
  self.dump_default_options = {
600
578
  :max_nesting => false,
601
579
  :allow_nan => true,
580
+ :escape_slash => false,
602
581
  }
603
582
 
604
- # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
605
- # the result.
583
+ # :call-seq:
584
+ # JSON.dump(obj, io = nil, limit = nil)
606
585
  #
607
- # If anIO (an IO-like object or an object that responds to the write method)
608
- # was given, the resulting JSON is written to it.
586
+ # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result.
609
587
  #
610
- # If the number of nested arrays or objects exceeds _limit_, an ArgumentError
611
- # exception is raised. This argument is similar (but not exactly the
612
- # same!) to the _limit_ argument in Marshal.dump.
588
+ # The default options can be changed via method JSON.dump_default_options.
613
589
  #
614
- # The default options for the generator can be changed via the
615
- # dump_default_options method.
590
+ # - Argument +io+, if given, should respond to method +write+;
591
+ # the \JSON \String is written to +io+, and +io+ is returned.
592
+ # If +io+ is not given, the \JSON \String is returned.
593
+ # - Argument +limit+, if given, is passed to JSON.generate as option +max_nesting+.
616
594
  #
617
- # This method is part of the implementation of the load/dump interface of
618
- # Marshal and YAML.
595
+ # ---
596
+ #
597
+ # When argument +io+ is not given, returns the \JSON \String generated from +obj+:
598
+ # obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
599
+ # json = JSON.dump(obj)
600
+ # json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}"
601
+ #
602
+ # When argument +io+ is given, writes the \JSON \String to +io+ and returns +io+:
603
+ # path = 't.json'
604
+ # File.open(path, 'w') do |file|
605
+ # JSON.dump(obj, file)
606
+ # end # => #<File:t.json (closed)>
607
+ # puts File.read(path)
608
+ # Output:
609
+ # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
619
610
  def dump(obj, anIO = nil, limit = nil)
620
611
  if anIO and limit.nil?
621
612
  anIO = anIO.to_io if anIO.respond_to?(:to_io)
Binary file
@@ -37,20 +37,26 @@ module JSON
37
37
  '\\' => '\\\\',
38
38
  } # :nodoc:
39
39
 
40
+ ESCAPE_SLASH_MAP = MAP.merge(
41
+ '/' => '\\/',
42
+ )
43
+
40
44
  # Convert a UTF8 encoded Ruby string _string_ to a JSON string, encoded with
41
45
  # UTF16 big endian characters as \u????, and return it.
42
- def utf8_to_json(string) # :nodoc:
46
+ def utf8_to_json(string, escape_slash = false) # :nodoc:
43
47
  string = string.dup
44
48
  string.force_encoding(::Encoding::ASCII_8BIT)
45
- string.gsub!(/["\\\x0-\x1f]/) { MAP[$&] }
49
+ map = escape_slash ? ESCAPE_SLASH_MAP : MAP
50
+ string.gsub!(/[\/"\\\x0-\x1f]/) { map[$&] || $& }
46
51
  string.force_encoding(::Encoding::UTF_8)
47
52
  string
48
53
  end
49
54
 
50
- def utf8_to_json_ascii(string) # :nodoc:
55
+ def utf8_to_json_ascii(string, escape_slash = false) # :nodoc:
51
56
  string = string.dup
52
57
  string.force_encoding(::Encoding::ASCII_8BIT)
53
- string.gsub!(/["\\\x0-\x1f]/n) { MAP[$&] }
58
+ map = escape_slash ? ESCAPE_SLASH_MAP : MAP
59
+ string.gsub!(/[\/"\\\x0-\x1f]/n) { map[$&] || $& }
54
60
  string.gsub!(/(
55
61
  (?:
56
62
  [\xc2-\xdf][\x80-\xbf] |
@@ -109,6 +115,7 @@ module JSON
109
115
  # * *space_before*: a string that is put before a : pair delimiter (default: ''),
110
116
  # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
111
117
  # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
118
+ # * *escape_slash*: true if forward slash (/) should be escaped (default: false)
112
119
  # * *check_circular*: is deprecated now, use the :max_nesting option instead,
113
120
  # * *max_nesting*: sets the maximum level of data structure nesting in
114
121
  # the generated JSON, max_nesting = 0 if no maximum should be checked.
@@ -123,6 +130,7 @@ module JSON
123
130
  @array_nl = ''
124
131
  @allow_nan = false
125
132
  @ascii_only = false
133
+ @escape_slash = false
126
134
  @buffer_initial_length = 1024
127
135
  configure opts
128
136
  end
@@ -148,6 +156,10 @@ module JSON
148
156
  # the generated JSON, max_nesting = 0 if no maximum is checked.
149
157
  attr_accessor :max_nesting
150
158
 
159
+ # If this attribute is set to true, forward slashes will be escaped in
160
+ # all json strings.
161
+ attr_accessor :escape_slash
162
+
151
163
  # :stopdoc:
152
164
  attr_reader :buffer_initial_length
153
165
 
@@ -187,6 +199,11 @@ module JSON
187
199
  @ascii_only
188
200
  end
189
201
 
202
+ # Returns true, if forward slashes are escaped. Otherwise returns false.
203
+ def escape_slash?
204
+ @escape_slash
205
+ end
206
+
190
207
  # Configure this State instance with the Hash _opts_, and return
191
208
  # itself.
192
209
  def configure(opts)
@@ -209,6 +226,7 @@ module JSON
209
226
  @ascii_only = opts[:ascii_only] if opts.key?(:ascii_only)
210
227
  @depth = opts[:depth] || 0
211
228
  @buffer_initial_length ||= opts[:buffer_initial_length]
229
+ @escape_slash = !!opts[:escape_slash] if opts.key?(:escape_slash)
212
230
 
213
231
  if !opts.key?(:max_nesting) # defaults to 100
214
232
  @max_nesting = 100
@@ -314,8 +332,10 @@ module JSON
314
332
  first = false
315
333
  }
316
334
  depth = state.depth -= 1
317
- result << state.object_nl
318
- result << state.indent * depth if indent
335
+ unless first
336
+ result << state.object_nl
337
+ result << state.indent * depth if indent
338
+ end
319
339
  result << '}'
320
340
  result
321
341
  end
@@ -399,9 +419,9 @@ module JSON
399
419
  string = encode(::Encoding::UTF_8)
400
420
  end
401
421
  if state.ascii_only?
402
- '"' << JSON.utf8_to_json_ascii(string) << '"'
422
+ '"' << JSON.utf8_to_json_ascii(string, state.escape_slash) << '"'
403
423
  else
404
- '"' << JSON.utf8_to_json(string) << '"'
424
+ '"' << JSON.utf8_to_json(string, state.escape_slash) << '"'
405
425
  end
406
426
  end
407
427
 
@@ -61,6 +61,8 @@ module JSON
61
61
  # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
62
62
  # defiance of RFC 7159 to be parsed by the Parser. This option defaults
63
63
  # to false.
64
+ # * *freeze*: If set to true, all parsed objects will be frozen. Parsed
65
+ # string will be deduplicated if possible.
64
66
  # * *symbolize_names*: If set to true, returns symbols for the names
65
67
  # (keys) in a JSON object. Otherwise strings are returned, which is
66
68
  # also the default. It's not possible to use this option in
@@ -86,6 +88,7 @@ module JSON
86
88
  end
87
89
  @allow_nan = !!opts[:allow_nan]
88
90
  @symbolize_names = !!opts[:symbolize_names]
91
+ @freeze = !!opts[:freeze]
89
92
  if opts.key?(:create_additions)
90
93
  @create_additions = !!opts[:create_additions]
91
94
  else
@@ -120,6 +123,7 @@ module JSON
120
123
  obj = parse_value
121
124
  UNPARSED.equal?(obj) and raise ParserError,
122
125
  "source is not valid JSON!"
126
+ obj.freeze if @freeze
123
127
  end
124
128
  while !eos? && skip(IGNORE) do end
125
129
  eos? or raise ParserError, "source is not valid JSON!"
@@ -161,6 +165,7 @@ module JSON
161
165
  EMPTY_8BIT_STRING.force_encoding Encoding::ASCII_8BIT
162
166
  end
163
167
 
168
+ STR_UMINUS = ''.respond_to?(:-@)
164
169
  def parse_string
165
170
  if scan(STRING)
166
171
  return '' if self[1].empty?
@@ -180,6 +185,15 @@ module JSON
180
185
  if string.respond_to?(:force_encoding)
181
186
  string.force_encoding(::Encoding::UTF_8)
182
187
  end
188
+
189
+ if @freeze
190
+ if STR_UMINUS
191
+ string = -string
192
+ else
193
+ string.freeze
194
+ end
195
+ end
196
+
183
197
  if @create_additions and @match_string
184
198
  for (regexp, klass) in @match_string
185
199
  klass.json_creatable? or next
@@ -242,8 +256,10 @@ module JSON
242
256
  @max_nesting.nonzero? && @current_nesting > @max_nesting
243
257
  result = @array_class.new
244
258
  delim = false
245
- until eos?
259
+ loop do
246
260
  case
261
+ when eos?
262
+ raise ParserError, "unexpected end of string while parsing array"
247
263
  when !UNPARSED.equal?(value = parse_value)
248
264
  delim = false
249
265
  result << value
@@ -274,8 +290,10 @@ module JSON
274
290
  @max_nesting.nonzero? && @current_nesting > @max_nesting
275
291
  result = @object_class.new
276
292
  delim = false
277
- until eos?
293
+ loop do
278
294
  case
295
+ when eos?
296
+ raise ParserError, "unexpected end of string while parsing object"
279
297
  when !UNPARSED.equal?(string = parse_string)
280
298
  skip(IGNORE)
281
299
  unless scan(PAIR_DELIMITER)
@@ -0,0 +1 @@
1
+ {
@@ -0,0 +1 @@
1
+ [
@@ -0,0 +1 @@
1
+ [1, 2, 3,
@@ -0,0 +1 @@
1
+ {"foo": "bar"
@@ -195,9 +195,5 @@ class JSONAdditionTest < Test::Unit::TestCase
195
195
  def test_set
196
196
  s = Set.new([:a, :b, :c, :a])
197
197
  assert_equal s, JSON.parse(JSON(s), :create_additions => true)
198
- ss = SortedSet.new([:d, :b, :a, :c])
199
- ss_again = JSON.parse(JSON(ss), :create_additions => true)
200
- assert_kind_of ss.class, ss_again
201
- assert_equal ss, ss_again
202
198
  end
203
199
  end
@@ -123,4 +123,47 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
123
123
  assert_equal @json, JSON(@hash)
124
124
  assert_equal @hash, JSON(@json)
125
125
  end
126
+
127
+ def test_load_file
128
+ test_load_shared(:load_file)
129
+ end
130
+
131
+ def test_load_file!
132
+ test_load_shared(:load_file!)
133
+ end
134
+
135
+ def test_load_file_with_option
136
+ test_load_file_with_option_shared(:load_file)
137
+ end
138
+
139
+ def test_load_file_with_option!
140
+ test_load_file_with_option_shared(:load_file!)
141
+ end
142
+
143
+ private
144
+
145
+ def test_load_shared(method_name)
146
+ temp_file_containing(@json) do |filespec|
147
+ assert_equal JSON.public_send(method_name, filespec), @hash
148
+ end
149
+ end
150
+
151
+ def test_load_file_with_option_shared(method_name)
152
+ temp_file_containing(@json) do |filespec|
153
+ parsed_object = JSON.public_send(method_name, filespec, symbolize_names: true)
154
+ key_classes = parsed_object.keys.map(&:class)
155
+ assert_include(key_classes, Symbol)
156
+ assert_not_include(key_classes, String)
157
+ end
158
+ end
159
+
160
+ def temp_file_containing(text, file_prefix = '')
161
+ raise "This method must be called with a code block." unless block_given?
162
+
163
+ Tempfile.create(file_prefix) do |file|
164
+ file << text
165
+ file.close
166
+ yield file.path
167
+ end
168
+ end
126
169
  end
@@ -10,6 +10,7 @@ class JSONFixturesTest < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  def test_passing
13
+ verbose_bak, $VERBOSE = $VERBOSE, nil
13
14
  for name, source in @passed
14
15
  begin
15
16
  assert JSON.parse(source),
@@ -19,6 +20,8 @@ class JSONFixturesTest < Test::Unit::TestCase
19
20
  raise e
20
21
  end
21
22
  end
23
+ ensure
24
+ $VERBOSE = verbose_bak
22
25
  end
23
26
 
24
27
  def test_failing
@@ -49,7 +49,6 @@ EOT
49
49
  end
50
50
 
51
51
  def test_remove_const_segv
52
- return if RUBY_ENGINE == 'jruby'
53
52
  stress = GC.stress
54
53
  const = JSON::SAFE_STATE_PROTOTYPE.dup
55
54
 
@@ -76,7 +75,7 @@ EOT
76
75
  silence do
77
76
  JSON.const_set :SAFE_STATE_PROTOTYPE, const
78
77
  end
79
- end if JSON.const_defined?("Ext")
78
+ end if JSON.const_defined?("Ext") && RUBY_ENGINE != 'jruby'
80
79
 
81
80
  def test_generate
82
81
  json = generate(@hash)
@@ -93,6 +92,11 @@ EOT
93
92
  end
94
93
 
95
94
  def test_generate_pretty
95
+ json = pretty_generate({})
96
+ assert_equal(<<'EOT'.chomp, json)
97
+ {
98
+ }
99
+ EOT
96
100
  json = pretty_generate(@hash)
97
101
  # hashes aren't (insertion) ordered on every ruby implementation
98
102
  # assert_equal(@json3, json)
@@ -174,6 +178,7 @@ EOT
174
178
  :ascii_only => false,
175
179
  :buffer_initial_length => 1024,
176
180
  :depth => 0,
181
+ :escape_slash => false,
177
182
  :indent => " ",
178
183
  :max_nesting => 100,
179
184
  :object_nl => "\n",
@@ -190,6 +195,7 @@ EOT
190
195
  :ascii_only => false,
191
196
  :buffer_initial_length => 1024,
192
197
  :depth => 0,
198
+ :escape_slash => false,
193
199
  :indent => "",
194
200
  :max_nesting => 100,
195
201
  :object_nl => "",
@@ -206,6 +212,7 @@ EOT
206
212
  :ascii_only => false,
207
213
  :buffer_initial_length => 1024,
208
214
  :depth => 0,
215
+ :escape_slash => false,
209
216
  :indent => "",
210
217
  :max_nesting => 0,
211
218
  :object_nl => "",
@@ -394,6 +401,10 @@ EOT
394
401
  json = '["/"]'
395
402
  assert_equal json, generate(data)
396
403
  #
404
+ data = [ '/' ]
405
+ json = '["\/"]'
406
+ assert_equal json, generate(data, :escape_slash => true)
407
+ #
397
408
  data = ['"']
398
409
  json = '["\""]'
399
410
  assert_equal json, generate(data)
@@ -218,6 +218,17 @@ class JSONParserTest < Test::Unit::TestCase
218
218
  end
219
219
  end
220
220
 
221
+ def test_freeze
222
+ assert_predicate parse('{}', :freeze => true), :frozen?
223
+ assert_predicate parse('[]', :freeze => true), :frozen?
224
+ assert_predicate parse('"foo"', :freeze => true), :frozen?
225
+
226
+ if string_deduplication_available?
227
+ assert_same(-'foo', parse('"foo"', :freeze => true))
228
+ assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first)
229
+ end
230
+ end
231
+
221
232
  def test_parse_comments
222
233
  json = <<EOT
223
234
  {
@@ -293,6 +304,10 @@ EOT
293
304
  json = '["\\\'"]'
294
305
  data = ["'"]
295
306
  assert_equal data, parse(json)
307
+
308
+ json = '["\/"]'
309
+ data = [ '/' ]
310
+ assert_equal data, parse(json)
296
311
  end
297
312
 
298
313
  class SubArray < Array
@@ -464,6 +479,16 @@ EOT
464
479
 
465
480
  private
466
481
 
482
+ def string_deduplication_available?
483
+ r1 = rand.to_s
484
+ r2 = r1.dup
485
+ begin
486
+ (-r1).equal?(-r2)
487
+ rescue NoMethodError
488
+ false # No String#-@
489
+ end
490
+ end
491
+
467
492
  def assert_equal_float(expected, actual, delta = 1e-2)
468
493
  Array === expected and expected = expected.first
469
494
  Array === actual and actual = actual.first
@@ -1,12 +1,12 @@
1
1
  case ENV['JSON']
2
2
  when 'pure'
3
- $:.unshift 'lib'
3
+ $:.unshift File.join(__dir__, '../lib')
4
4
  require 'json/pure'
5
5
  when 'ext'
6
- $:.unshift 'ext', 'lib'
6
+ $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
7
7
  require 'json/ext'
8
8
  else
9
- $:.unshift 'ext', 'lib'
9
+ $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
10
10
  require 'json'
11
11
  end
12
12
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.4.0
5
5
  platform: java
6
6
  authors:
7
7
  - Daniel Luz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-30 00:00:00.000000000 Z
11
+ date: 2020-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -50,6 +50,7 @@ executables: []
50
50
  extensions: []
51
51
  extra_rdoc_files: []
52
52
  files:
53
+ - LICENSE
53
54
  - lib/json.rb
54
55
  - lib/json/add/bigdecimal.rb
55
56
  - lib/json/add/complex.rb
@@ -67,6 +68,8 @@ files:
67
68
  - lib/json/add/time.rb
68
69
  - lib/json/common.rb
69
70
  - lib/json/ext.rb
71
+ - lib/json/ext/generator.jar
72
+ - lib/json/ext/parser.jar
70
73
  - lib/json/generic_object.rb
71
74
  - lib/json/pure.rb
72
75
  - lib/json/pure/generator.rb
@@ -88,7 +91,11 @@ files:
88
91
  - tests/fixtures/fail25.json
89
92
  - tests/fixtures/fail27.json
90
93
  - tests/fixtures/fail28.json
94
+ - tests/fixtures/fail29.json
91
95
  - tests/fixtures/fail3.json
96
+ - tests/fixtures/fail30.json
97
+ - tests/fixtures/fail31.json
98
+ - tests/fixtures/fail32.json
92
99
  - tests/fixtures/fail4.json
93
100
  - tests/fixtures/fail5.json
94
101
  - tests/fixtures/fail6.json
@@ -116,7 +123,13 @@ files:
116
123
  homepage: http://flori.github.com/json
117
124
  licenses:
118
125
  - Ruby
119
- metadata: {}
126
+ metadata:
127
+ bug_tracker_uri: https://github.com/flori/json/issues
128
+ changelog_uri: https://github.com/flori/json/blob/master/CHANGES.md
129
+ documentation_uri: http://flori.github.io/json/doc/index.html
130
+ homepage_uri: http://flori.github.io/json/
131
+ source_code_uri: https://github.com/flori/json
132
+ wiki_uri: https://github.com/flori/json/wiki
120
133
  post_install_message:
121
134
  rdoc_options: []
122
135
  require_paths:
@@ -125,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
138
  requirements:
126
139
  - - ">="
127
140
  - !ruby/object:Gem::Version
128
- version: '0'
141
+ version: '2.0'
129
142
  required_rubygems_version: !ruby/object:Gem::Requirement
130
143
  requirements:
131
144
  - - ">="
@@ -135,5 +148,6 @@ requirements: []
135
148
  rubygems_version: 3.0.6
136
149
  signing_key:
137
150
  specification_version: 4
138
- summary: JSON implementation for JRuby
139
- test_files: []
151
+ summary: JSON Implementation for Ruby
152
+ test_files:
153
+ - tests/test_helper.rb