json 1.8.3 → 2.5.1

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