json 1.8.3 → 2.5.1

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