json 2.3.1-java → 2.4.0-java

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 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