json_pure 2.2.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +51 -0
  3. data/LICENSE +56 -0
  4. data/README.md +17 -1
  5. data/VERSION +1 -1
  6. data/json_pure.gemspec +49 -26
  7. data/lib/json.rb +549 -29
  8. data/lib/json/add/bigdecimal.rb +2 -2
  9. data/lib/json/add/complex.rb +2 -3
  10. data/lib/json/add/rational.rb +2 -3
  11. data/lib/json/add/regexp.rb +2 -2
  12. data/lib/json/common.rb +370 -125
  13. data/lib/json/pure/generator.rb +31 -10
  14. data/lib/json/pure/parser.rb +31 -5
  15. data/lib/json/version.rb +1 -1
  16. data/tests/fixtures/fail29.json +1 -0
  17. data/tests/fixtures/fail30.json +1 -0
  18. data/tests/fixtures/fail31.json +1 -0
  19. data/tests/fixtures/fail32.json +1 -0
  20. data/tests/json_addition_test.rb +0 -4
  21. data/tests/json_common_interface_test.rb +47 -4
  22. data/tests/json_fixtures_test.rb +9 -1
  23. data/tests/json_generator_test.rb +30 -8
  24. data/tests/json_parser_test.rb +39 -14
  25. data/tests/lib/core_assertions.rb +763 -0
  26. data/tests/lib/envutil.rb +365 -0
  27. data/tests/lib/find_executable.rb +22 -0
  28. data/tests/lib/helper.rb +4 -0
  29. data/tests/ractor_test.rb +30 -0
  30. data/tests/test_helper.rb +3 -3
  31. metadata +28 -48
  32. data/.gitignore +0 -17
  33. data/.travis.yml +0 -23
  34. data/README-json-jruby.md +0 -33
  35. data/Rakefile +0 -408
  36. data/diagrams/.keep +0 -0
  37. data/ext/json/ext/fbuffer/fbuffer.h +0 -187
  38. data/ext/json/ext/generator/depend +0 -1
  39. data/ext/json/ext/generator/extconf.rb +0 -4
  40. data/ext/json/ext/generator/generator.c +0 -1444
  41. data/ext/json/ext/generator/generator.h +0 -171
  42. data/ext/json/ext/parser/depend +0 -1
  43. data/ext/json/ext/parser/extconf.rb +0 -6
  44. data/ext/json/ext/parser/parser.c +0 -2131
  45. data/ext/json/ext/parser/parser.h +0 -91
  46. data/ext/json/ext/parser/parser.rl +0 -891
  47. data/ext/json/extconf.rb +0 -2
  48. data/install.rb +0 -23
  49. data/java/src/json/ext/ByteListTranscoder.java +0 -166
  50. data/java/src/json/ext/Generator.java +0 -443
  51. data/java/src/json/ext/GeneratorMethods.java +0 -231
  52. data/java/src/json/ext/GeneratorService.java +0 -42
  53. data/java/src/json/ext/GeneratorState.java +0 -490
  54. data/java/src/json/ext/OptionsReader.java +0 -113
  55. data/java/src/json/ext/Parser.java +0 -2362
  56. data/java/src/json/ext/Parser.rl +0 -893
  57. data/java/src/json/ext/ParserService.java +0 -34
  58. data/java/src/json/ext/RuntimeInfo.java +0 -116
  59. data/java/src/json/ext/StringDecoder.java +0 -166
  60. data/java/src/json/ext/StringEncoder.java +0 -111
  61. data/java/src/json/ext/Utils.java +0 -88
  62. data/json-java.gemspec +0 -38
  63. data/json.gemspec +0 -0
  64. data/references/rfc7159.txt +0 -899
  65. data/tools/diff.sh +0 -18
  66. data/tools/fuzz.rb +0 -131
  67. data/tools/server.rb +0 -62
@@ -23,7 +23,7 @@ class BigDecimal
23
23
  end
24
24
 
25
25
  # return the JSON value
26
- def to_json(*)
27
- as_json.to_json
26
+ def to_json(*args)
27
+ as_json.to_json(*args)
28
28
  end
29
29
  end
@@ -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
 
@@ -23,7 +22,7 @@ class Complex
23
22
  end
24
23
 
25
24
  # Stores class name (Complex) along with real value <tt>r</tt> and imaginary value <tt>i</tt> as JSON string
26
- def to_json(*)
27
- as_json.to_json
25
+ def to_json(*args)
26
+ as_json.to_json(*args)
28
27
  end
29
28
  end
@@ -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>,
@@ -22,7 +21,7 @@ class Rational
22
21
  end
23
22
 
24
23
  # Stores class name (Rational) along with numerator value <tt>n</tt> and denominator value <tt>d</tt> as JSON string
25
- def to_json(*)
26
- as_json.to_json
24
+ def to_json(*args)
25
+ as_json.to_json(*args)
27
26
  end
28
27
  end
@@ -24,7 +24,7 @@ class Regexp
24
24
 
25
25
  # Stores class name (Regexp) with options <tt>o</tt> and source <tt>s</tt>
26
26
  # (Regexp or String) as JSON string
27
- def to_json(*)
28
- as_json.to_json
27
+ def to_json(*args)
28
+ as_json.to_json(*args)
29
29
  end
30
30
  end
@@ -4,12 +4,17 @@ require 'json/generic_object'
4
4
 
5
5
  module JSON
6
6
  class << self
7
- # If _object_ is string-like, parse the string and return the parsed
8
- # result as a Ruby data structure. Otherwise generate a JSON text from the
9
- # Ruby data structure object and return it.
7
+ # :call-seq:
8
+ # JSON[object] -> new_array or new_string
10
9
  #
11
- # The _opts_ argument is passed through to generate/parse respectively.
12
- # See generate and parse for their documentation.
10
+ # If +object+ is a \String,
11
+ # calls JSON.parse with +object+ and +opts+ (see method #parse):
12
+ # json = '[0, 1, null]'
13
+ # JSON[json]# => [0, 1, nil]
14
+ #
15
+ # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
16
+ # ruby = [0, 1, nil]
17
+ # JSON[ruby] # => '[0,1,null]'
13
18
  def [](object, opts = {})
14
19
  if object.respond_to? :to_str
15
20
  JSON.parse(object.to_str, opts)
@@ -19,7 +24,8 @@ module JSON
19
24
  end
20
25
 
21
26
  # Returns the JSON parser class that is used by JSON. This is either
22
- # JSON::Ext::Parser or JSON::Pure::Parser.
27
+ # JSON::Ext::Parser or JSON::Pure::Parser:
28
+ # JSON.parser # => JSON::Ext::Parser
23
29
  attr_reader :parser
24
30
 
25
31
  # Set the JSON parser class _parser_ to be used by JSON.
@@ -65,37 +71,59 @@ module JSON
65
71
  end
66
72
  self.state = generator::State
67
73
  const_set :State, self.state
68
- const_set :SAFE_STATE_PROTOTYPE, State.new
69
- const_set :FAST_STATE_PROTOTYPE, State.new(
74
+ const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby
75
+ ensure
76
+ $VERBOSE = old
77
+ end
78
+
79
+ def create_fast_state
80
+ State.new(
70
81
  :indent => '',
71
82
  :space => '',
72
83
  :object_nl => "",
73
84
  :array_nl => "",
74
85
  :max_nesting => false
75
86
  )
76
- const_set :PRETTY_STATE_PROTOTYPE, State.new(
87
+ end
88
+
89
+ def create_pretty_state
90
+ State.new(
77
91
  :indent => ' ',
78
92
  :space => ' ',
79
93
  :object_nl => "\n",
80
94
  :array_nl => "\n"
81
95
  )
82
- ensure
83
- $VERBOSE = old
84
96
  end
85
97
 
86
98
  # Returns the JSON generator module that is used by JSON. This is
87
- # either JSON::Ext::Generator or JSON::Pure::Generator.
99
+ # either JSON::Ext::Generator or JSON::Pure::Generator:
100
+ # JSON.generator # => JSON::Ext::Generator
88
101
  attr_reader :generator
89
102
 
90
- # Returns the JSON generator state class that is used by JSON. This is
91
- # either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
103
+ # Sets or Returns the JSON generator state class that is used by JSON. This is
104
+ # either JSON::Ext::Generator::State or JSON::Pure::Generator::State:
105
+ # JSON.state # => JSON::Ext::Generator::State
92
106
  attr_accessor :state
107
+ end
108
+
109
+ DEFAULT_CREATE_ID = 'json_class'.freeze
110
+ private_constant :DEFAULT_CREATE_ID
111
+
112
+ CREATE_ID_TLS_KEY = "JSON.create_id".freeze
113
+ private_constant :CREATE_ID_TLS_KEY
114
+
115
+ # Sets create identifier, which is used to decide if the _json_create_
116
+ # hook of a class should be called; initial value is +json_class+:
117
+ # JSON.create_id # => 'json_class'
118
+ def self.create_id=(new_value)
119
+ Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze
120
+ end
93
121
 
94
- # This is create identifier, which is used to decide if the _json_create_
95
- # hook of a class should be called. It defaults to 'json_class'.
96
- attr_accessor :create_id
122
+ # Returns the current create identifier.
123
+ # See also JSON.create_id=.
124
+ def self.create_id
125
+ Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID
97
126
  end
98
- self.create_id = 'json_class'
99
127
 
100
128
  NaN = 0.0/0
101
129
 
@@ -126,7 +154,7 @@ module JSON
126
154
  # This exception is raised if a generator or unparser error occurs.
127
155
  class GeneratorError < JSONError; end
128
156
  # For backwards compatibility
129
- UnparserError = GeneratorError
157
+ UnparserError = GeneratorError # :nodoc:
130
158
 
131
159
  # This exception is raised if the required unicode support is missing on the
132
160
  # system. Usually this means that the iconv library is not installed.
@@ -134,82 +162,140 @@ module JSON
134
162
 
135
163
  module_function
136
164
 
137
- # Parse the JSON document _source_ into a Ruby data structure and return it.
138
- #
139
- # _opts_ can have the following
140
- # keys:
141
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
142
- # structures. Disable depth checking with :max_nesting => false. It
143
- # defaults to 100.
144
- # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
145
- # defiance of RFC 7159 to be parsed by the Parser. This option defaults
146
- # to false.
147
- # * *symbolize_names*: If set to true, returns symbols for the names
148
- # (keys) in a JSON object. Otherwise strings are returned. Strings are
149
- # the default.
150
- # * *create_additions*: If set to false, the Parser doesn't create
151
- # additions even if a matching class and create_id was found. This option
152
- # defaults to false.
153
- # * *object_class*: Defaults to Hash
154
- # * *array_class*: Defaults to Array
165
+ # :call-seq:
166
+ # JSON.parse(source, opts) -> object
167
+ #
168
+ # Returns the Ruby objects created by parsing the given +source+.
169
+ #
170
+ # Argument +source+ contains the \String to be parsed.
171
+ #
172
+ # Argument +opts+, if given, contains a \Hash of options for the parsing.
173
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
174
+ #
175
+ # ---
176
+ #
177
+ # When +source+ is a \JSON array, returns a Ruby \Array:
178
+ # source = '["foo", 1.0, true, false, null]'
179
+ # ruby = JSON.parse(source)
180
+ # ruby # => ["foo", 1.0, true, false, nil]
181
+ # ruby.class # => Array
182
+ #
183
+ # When +source+ is a \JSON object, returns a Ruby \Hash:
184
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
185
+ # ruby = JSON.parse(source)
186
+ # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
187
+ # ruby.class # => Hash
188
+ #
189
+ # For examples of parsing for all \JSON data types, see
190
+ # {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
191
+ #
192
+ # Parses nested JSON objects:
193
+ # source = <<-EOT
194
+ # {
195
+ # "name": "Dave",
196
+ # "age" :40,
197
+ # "hats": [
198
+ # "Cattleman's",
199
+ # "Panama",
200
+ # "Tophat"
201
+ # ]
202
+ # }
203
+ # EOT
204
+ # ruby = JSON.parse(source)
205
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
206
+ #
207
+ # ---
208
+ #
209
+ # Raises an exception if +source+ is not valid JSON:
210
+ # # Raises JSON::ParserError (783: unexpected token at ''):
211
+ # JSON.parse('')
212
+ #
155
213
  def parse(source, opts = {})
156
- Parser.new(source, opts).parse
214
+ Parser.new(source, **(opts||{})).parse
157
215
  end
158
216
 
159
- # Parse the JSON document _source_ into a Ruby data structure and return it.
160
- # The bang version of the parse method defaults to the more dangerous values
161
- # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
162
- #
163
- # _opts_ can have the following keys:
164
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
165
- # structures. Enable depth checking with :max_nesting => anInteger. The
166
- # parse! methods defaults to not doing max depth checking: This can be
167
- # dangerous if someone wants to fill up your stack.
168
- # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
169
- # defiance of RFC 7159 to be parsed by the Parser. This option defaults
170
- # to true.
171
- # * *create_additions*: If set to false, the Parser doesn't create
172
- # additions even if a matching class and create_id was found. This option
173
- # defaults to false.
217
+ # :call-seq:
218
+ # JSON.parse!(source, opts) -> object
219
+ #
220
+ # Calls
221
+ # parse(source, opts)
222
+ # with +source+ and possibly modified +opts+.
223
+ #
224
+ # Differences from JSON.parse:
225
+ # - Option +max_nesting+, if not provided, defaults to +false+,
226
+ # which disables checking for nesting depth.
227
+ # - Option +allow_nan+, if not provided, defaults to +true+.
174
228
  def parse!(source, opts = {})
175
229
  opts = {
176
230
  :max_nesting => false,
177
231
  :allow_nan => true
178
232
  }.merge(opts)
179
- Parser.new(source, opts).parse
233
+ Parser.new(source, **(opts||{})).parse
234
+ end
235
+
236
+ # :call-seq:
237
+ # JSON.load_file(path, opts={}) -> object
238
+ #
239
+ # Calls:
240
+ # parse(File.read(path), opts)
241
+ #
242
+ # See method #parse.
243
+ def load_file(filespec, opts = {})
244
+ parse(File.read(filespec), opts)
180
245
  end
181
246
 
182
- # Generate a JSON document from the Ruby data structure _obj_ and return
183
- # it. _state_ is * a JSON::State object,
184
- # * or a Hash like object (responding to to_hash),
185
- # * an object convertible into a hash by a to_h method,
186
- # that is used as or to configure a State object.
187
- #
188
- # It defaults to a state object, that creates the shortest possible JSON text
189
- # in one line, checks for circular data structures and doesn't allow NaN,
190
- # Infinity, and -Infinity.
191
- #
192
- # A _state_ hash can have the following keys:
193
- # * *indent*: a string used to indent levels (default: ''),
194
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
195
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
196
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
197
- # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
198
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
199
- # generated, otherwise an exception is thrown if these values are
200
- # encountered. This options defaults to false.
201
- # * *max_nesting*: The maximum depth of nesting allowed in the data
202
- # structures from which JSON is to be generated. Disable depth checking
203
- # with :max_nesting => false, it defaults to 100.
204
- #
205
- # See also the fast_generate for the fastest creation method with the least
206
- # amount of sanity checks, and the pretty_generate method for some
207
- # defaults for pretty output.
247
+ # :call-seq:
248
+ # JSON.load_file!(path, opts = {})
249
+ #
250
+ # Calls:
251
+ # JSON.parse!(File.read(path, opts))
252
+ #
253
+ # See method #parse!
254
+ def load_file!(filespec, opts = {})
255
+ parse!(File.read(filespec), opts)
256
+ end
257
+
258
+ # :call-seq:
259
+ # JSON.generate(obj, opts = nil) -> new_string
260
+ #
261
+ # Returns a \String containing the generated \JSON data.
262
+ #
263
+ # See also JSON.fast_generate, JSON.pretty_generate.
264
+ #
265
+ # Argument +obj+ is the Ruby object to be converted to \JSON.
266
+ #
267
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
268
+ # See {Generating Options}[#module-JSON-label-Generating+Options].
269
+ #
270
+ # ---
271
+ #
272
+ # When +obj+ is an \Array, returns a \String containing a \JSON array:
273
+ # obj = ["foo", 1.0, true, false, nil]
274
+ # json = JSON.generate(obj)
275
+ # json # => '["foo",1.0,true,false,null]'
276
+ #
277
+ # When +obj+ is a \Hash, returns a \String containing a \JSON object:
278
+ # obj = {foo: 0, bar: 's', baz: :bat}
279
+ # json = JSON.generate(obj)
280
+ # json # => '{"foo":0,"bar":"s","baz":"bat"}'
281
+ #
282
+ # For examples of generating from other Ruby objects, see
283
+ # {Generating \JSON from Other Objects}[#module-JSON-label-Generating+JSON+from+Other+Objects].
284
+ #
285
+ # ---
286
+ #
287
+ # Raises an exception if any formatting option is not a \String.
288
+ #
289
+ # Raises an exception if +obj+ contains circular references:
290
+ # a = []; b = []; a.push(b); b.push(a)
291
+ # # Raises JSON::NestingError (nesting of 100 is too deep):
292
+ # JSON.generate(a)
293
+ #
208
294
  def generate(obj, opts = nil)
209
295
  if State === opts
210
296
  state, opts = opts, nil
211
297
  else
212
- state = SAFE_STATE_PROTOTYPE.dup
298
+ state = State.new
213
299
  end
214
300
  if opts
215
301
  if opts.respond_to? :to_hash
@@ -231,16 +317,24 @@ module JSON
231
317
  module_function :unparse
232
318
  # :startdoc:
233
319
 
234
- # Generate a JSON document from the Ruby data structure _obj_ and return it.
235
- # This method disables the checks for circles in Ruby objects.
320
+ # :call-seq:
321
+ # JSON.fast_generate(obj, opts) -> new_string
322
+ #
323
+ # Arguments +obj+ and +opts+ here are the same as
324
+ # arguments +obj+ and +opts+ in JSON.generate.
325
+ #
326
+ # By default, generates \JSON data without checking
327
+ # for circular references in +obj+ (option +max_nesting+ set to +false+, disabled).
236
328
  #
237
- # *WARNING*: Be careful not to pass any Ruby data structures with circles as
238
- # _obj_ argument because this will cause JSON to go into an infinite loop.
329
+ # Raises an exception if +obj+ contains circular references:
330
+ # a = []; b = []; a.push(b); b.push(a)
331
+ # # Raises SystemStackError (stack level too deep):
332
+ # JSON.fast_generate(a)
239
333
  def fast_generate(obj, opts = nil)
240
334
  if State === opts
241
335
  state, opts = opts, nil
242
336
  else
243
- state = FAST_STATE_PROTOTYPE.dup
337
+ state = JSON.create_fast_state
244
338
  end
245
339
  if opts
246
340
  if opts.respond_to? :to_hash
@@ -261,17 +355,41 @@ module JSON
261
355
  module_function :fast_unparse
262
356
  # :startdoc:
263
357
 
264
- # Generate a JSON document from the Ruby data structure _obj_ and return it.
265
- # The returned document is a prettier form of the document returned by
266
- # #unparse.
358
+ # :call-seq:
359
+ # JSON.pretty_generate(obj, opts = nil) -> new_string
360
+ #
361
+ # Arguments +obj+ and +opts+ here are the same as
362
+ # arguments +obj+ and +opts+ in JSON.generate.
363
+ #
364
+ # Default options are:
365
+ # {
366
+ # indent: ' ', # Two spaces
367
+ # space: ' ', # One space
368
+ # array_nl: "\n", # Newline
369
+ # object_nl: "\n" # Newline
370
+ # }
371
+ #
372
+ # Example:
373
+ # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
374
+ # json = JSON.pretty_generate(obj)
375
+ # puts json
376
+ # Output:
377
+ # {
378
+ # "foo": [
379
+ # "bar",
380
+ # "baz"
381
+ # ],
382
+ # "bat": {
383
+ # "bam": 0,
384
+ # "bad": 1
385
+ # }
386
+ # }
267
387
  #
268
- # The _opts_ argument can be used to configure the generator. See the
269
- # generate method for a more detailed explanation.
270
388
  def pretty_generate(obj, opts = nil)
271
389
  if State === opts
272
390
  state, opts = opts, nil
273
391
  else
274
- state = PRETTY_STATE_PROTOTYPE.dup
392
+ state = JSON.create_pretty_state
275
393
  end
276
394
  if opts
277
395
  if opts.respond_to? :to_hash
@@ -293,10 +411,10 @@ module JSON
293
411
  # :startdoc:
294
412
 
295
413
  class << self
296
- # The global default options for the JSON.load method:
297
- # :max_nesting: false
298
- # :allow_nan: true
299
- # :allow_blank: true
414
+ # Sets or returns default options for the JSON.load method.
415
+ # Initially:
416
+ # opts = JSON.load_default_options
417
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
300
418
  attr_accessor :load_default_options
301
419
  end
302
420
  self.load_default_options = {
@@ -306,20 +424,134 @@ module JSON
306
424
  :create_additions => true,
307
425
  }
308
426
 
309
- # Load a ruby data structure from a JSON _source_ and return it. A source can
310
- # either be a string-like object, an IO-like object, or an object responding
311
- # to the read method. If _proc_ was given, it will be called with any nested
312
- # Ruby object as an argument recursively in depth first order. To modify the
313
- # default options pass in the optional _options_ argument as well.
427
+ # :call-seq:
428
+ # JSON.load(source, proc = nil, options = {}) -> object
429
+ #
430
+ # Returns the Ruby objects created by parsing the given +source+.
431
+ #
432
+ # - Argument +source+ must be, or be convertible to, a \String:
433
+ # - If +source+ responds to instance method +to_str+,
434
+ # <tt>source.to_str</tt> becomes the source.
435
+ # - If +source+ responds to instance method +to_io+,
436
+ # <tt>source.to_io.read</tt> becomes the source.
437
+ # - If +source+ responds to instance method +read+,
438
+ # <tt>source.read</tt> becomes the source.
439
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
440
+ # - Option +allow_blank+ specifies a truthy value.
441
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
442
+ # - Otherwise, +source+ remains the source.
443
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
444
+ # It will be called recursively with each result (depth-first order).
445
+ # See details below.
446
+ # BEWARE: This method is meant to serialise data from trusted user input,
447
+ # like from your own database server or clients under your control, it could
448
+ # be dangerous to allow untrusted users to pass JSON sources into it.
449
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
450
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
451
+ # The default options can be changed via method JSON.load_default_options=.
452
+ #
453
+ # ---
454
+ #
455
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
456
+ # <tt>parse(source, opts)</tt>; see #parse.
457
+ #
458
+ # Source for following examples:
459
+ # source = <<-EOT
460
+ # {
461
+ # "name": "Dave",
462
+ # "age" :40,
463
+ # "hats": [
464
+ # "Cattleman's",
465
+ # "Panama",
466
+ # "Tophat"
467
+ # ]
468
+ # }
469
+ # EOT
314
470
  #
315
- # BEWARE: This method is meant to serialise data from trusted user input,
316
- # like from your own database server or clients under your control, it could
317
- # be dangerous to allow untrusted users to pass JSON sources into it. The
318
- # default options for the parser can be changed via the load_default_options
319
- # method.
471
+ # Load a \String:
472
+ # ruby = JSON.load(source)
473
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
474
+ #
475
+ # Load an \IO object:
476
+ # require 'stringio'
477
+ # object = JSON.load(StringIO.new(source))
478
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
479
+ #
480
+ # Load a \File object:
481
+ # path = 't.json'
482
+ # File.write(path, source)
483
+ # File.open(path) do |file|
484
+ # JSON.load(file)
485
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
486
+ #
487
+ # ---
488
+ #
489
+ # When +proc+ is given:
490
+ # - Modifies +source+ as above.
491
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
492
+ # - Recursively calls <tt>proc(result)</tt>.
493
+ # - Returns the final result.
494
+ #
495
+ # Example:
496
+ # require 'json'
497
+ #
498
+ # # Some classes for the example.
499
+ # class Base
500
+ # def initialize(attributes)
501
+ # @attributes = attributes
502
+ # end
503
+ # end
504
+ # class User < Base; end
505
+ # class Account < Base; end
506
+ # class Admin < Base; end
507
+ # # The JSON source.
508
+ # json = <<-EOF
509
+ # {
510
+ # "users": [
511
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
512
+ # {"type": "User", "username": "john", "email": "john@example.com"}
513
+ # ],
514
+ # "accounts": [
515
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
516
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
517
+ # ],
518
+ # "admins": {"type": "Admin", "password": "0wn3d"}
519
+ # }
520
+ # EOF
521
+ # # Deserializer method.
522
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
523
+ # type = obj.is_a?(Hash) && obj["type"]
524
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
525
+ # end
526
+ # # Call to JSON.load
527
+ # ruby = JSON.load(json, proc {|obj|
528
+ # case obj
529
+ # when Hash
530
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
531
+ # when Array
532
+ # obj.map! {|v| deserialize_obj v }
533
+ # end
534
+ # })
535
+ # pp ruby
536
+ # Output:
537
+ # {"users"=>
538
+ # [#<User:0x00000000064c4c98
539
+ # @attributes=
540
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
541
+ # #<User:0x00000000064c4bd0
542
+ # @attributes=
543
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
544
+ # "accounts"=>
545
+ # [{"account"=>
546
+ # #<Account:0x00000000064c4928
547
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
548
+ # {"account"=>
549
+ # #<Account:0x00000000064c4680
550
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
551
+ # "admins"=>
552
+ # #<Admin:0x00000000064c41f8
553
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
320
554
  #
321
- # This method is part of the implementation of the load/dump interface of
322
- # Marshal and YAML.
323
555
  def load(source, proc = nil, options = {})
324
556
  opts = load_default_options.merge options
325
557
  if source.respond_to? :to_str
@@ -338,7 +570,7 @@ module JSON
338
570
  end
339
571
 
340
572
  # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
341
- def recurse_proc(result, &proc)
573
+ def recurse_proc(result, &proc) # :nodoc:
342
574
  case result
343
575
  when Array
344
576
  result.each { |x| recurse_proc x, &proc }
@@ -355,32 +587,45 @@ module JSON
355
587
  module_function :restore
356
588
 
357
589
  class << self
358
- # The global default options for the JSON.dump method:
359
- # :max_nesting: false
360
- # :allow_nan: true
361
- # :allow_blank: true
590
+ # Sets or returns the default options for the JSON.dump method.
591
+ # Initially:
592
+ # opts = JSON.dump_default_options
593
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
362
594
  attr_accessor :dump_default_options
363
595
  end
364
596
  self.dump_default_options = {
365
597
  :max_nesting => false,
366
598
  :allow_nan => true,
599
+ :escape_slash => false,
367
600
  }
368
601
 
369
- # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
370
- # the result.
602
+ # :call-seq:
603
+ # JSON.dump(obj, io = nil, limit = nil)
604
+ #
605
+ # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result.
606
+ #
607
+ # The default options can be changed via method JSON.dump_default_options.
371
608
  #
372
- # If anIO (an IO-like object or an object that responds to the write method)
373
- # was given, the resulting JSON is written to it.
609
+ # - Argument +io+, if given, should respond to method +write+;
610
+ # the \JSON \String is written to +io+, and +io+ is returned.
611
+ # If +io+ is not given, the \JSON \String is returned.
612
+ # - Argument +limit+, if given, is passed to JSON.generate as option +max_nesting+.
374
613
  #
375
- # If the number of nested arrays or objects exceeds _limit_, an ArgumentError
376
- # exception is raised. This argument is similar (but not exactly the
377
- # same!) to the _limit_ argument in Marshal.dump.
614
+ # ---
378
615
  #
379
- # The default options for the generator can be changed via the
380
- # dump_default_options method.
616
+ # When argument +io+ is not given, returns the \JSON \String generated from +obj+:
617
+ # obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
618
+ # json = JSON.dump(obj)
619
+ # json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}"
381
620
  #
382
- # This method is part of the implementation of the load/dump interface of
383
- # Marshal and YAML.
621
+ # When argument +io+ is given, writes the \JSON \String to +io+ and returns +io+:
622
+ # path = 't.json'
623
+ # File.open(path, 'w') do |file|
624
+ # JSON.dump(obj, file)
625
+ # end # => #<File:t.json (closed)>
626
+ # puts File.read(path)
627
+ # Output:
628
+ # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
384
629
  def dump(obj, anIO = nil, limit = nil)
385
630
  if anIO and limit.nil?
386
631
  anIO = anIO.to_io if anIO.respond_to?(:to_io)
@@ -402,7 +647,7 @@ module JSON
402
647
  raise ArgumentError, "exceed depth limit"
403
648
  end
404
649
 
405
- # Encodes string using Ruby's _String.encode_
650
+ # Encodes string using String.encode.
406
651
  def self.iconv(to, from, string)
407
652
  string.encode(to, from)
408
653
  end