json 2.3.1 → 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.
- checksums.yaml +4 -4
- data/CHANGES.md +22 -0
- data/LICENSE +56 -0
- data/VERSION +1 -1
- data/ext/json/ext/generator/generator.c +60 -11
- data/ext/json/ext/generator/generator.h +5 -2
- data/ext/json/ext/parser/extconf.rb +25 -0
- data/ext/json/ext/parser/parser.c +110 -68
- data/ext/json/ext/parser/parser.h +1 -0
- data/ext/json/ext/parser/parser.rl +67 -25
- data/ext/json/extconf.rb +1 -0
- data/json.gemspec +11 -77
- data/lib/json.rb +171 -0
- data/lib/json/add/complex.rb +0 -1
- data/lib/json/add/rational.rb +0 -1
- data/lib/json/common.rb +240 -228
- data/lib/json/pure/generator.rb +28 -8
- data/lib/json/pure/parser.rb +20 -2
- data/lib/json/version.rb +1 -1
- data/tests/fixtures/fail29.json +1 -0
- data/tests/fixtures/fail30.json +1 -0
- data/tests/fixtures/fail31.json +1 -0
- data/tests/fixtures/fail32.json +1 -0
- data/tests/json_addition_test.rb +0 -4
- data/tests/json_common_interface_test.rb +43 -0
- data/tests/json_fixtures_test.rb +3 -0
- data/tests/json_generator_test.rb +16 -38
- data/tests/json_parser_test.rb +25 -0
- data/tests/lib/core_assertions.rb +763 -0
- data/tests/lib/envutil.rb +365 -0
- data/tests/lib/find_executable.rb +22 -0
- data/tests/lib/helper.rb +4 -0
- data/tests/ractor_test.rb +30 -0
- data/tests/test_helper.rb +3 -3
- metadata +16 -37
- data/.gitignore +0 -18
- data/.travis.yml +0 -26
- data/README-json-jruby.md +0 -33
- data/Rakefile +0 -334
- data/diagrams/.keep +0 -0
- data/install.rb +0 -23
- data/java/src/json/ext/ByteListTranscoder.java +0 -166
- data/java/src/json/ext/Generator.java +0 -466
- data/java/src/json/ext/GeneratorMethods.java +0 -231
- data/java/src/json/ext/GeneratorService.java +0 -42
- data/java/src/json/ext/GeneratorState.java +0 -490
- data/java/src/json/ext/OptionsReader.java +0 -113
- data/java/src/json/ext/Parser.java +0 -2362
- data/java/src/json/ext/Parser.rl +0 -893
- data/java/src/json/ext/ParserService.java +0 -34
- data/java/src/json/ext/RuntimeInfo.java +0 -116
- data/java/src/json/ext/StringDecoder.java +0 -166
- data/java/src/json/ext/StringEncoder.java +0 -111
- data/java/src/json/ext/Utils.java +0 -88
- data/json-java.gemspec +0 -37
- data/json_pure.gemspec +0 -33
- data/references/rfc7159.txt +0 -899
- data/tools/diff.sh +0 -18
- data/tools/fuzz.rb +0 -131
- data/tools/server.rb +0 -62
    
        data/lib/json/add/complex.rb
    CHANGED
    
    
    
        data/lib/json/add/rational.rb
    CHANGED
    
    
    
        data/lib/json/common.rb
    CHANGED
    
    | @@ -4,13 +4,15 @@ require 'json/generic_object' | |
| 4 4 |  | 
| 5 5 | 
             
            module JSON
         | 
| 6 6 | 
             
              class << self
         | 
| 7 | 
            -
                #  | 
| 8 | 
            -
                #  | 
| 9 | 
            -
                # | 
| 7 | 
            +
                # :call-seq:
         | 
| 8 | 
            +
                #   JSON[object] -> new_array or new_string
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # If +object+ is a \String,
         | 
| 11 | 
            +
                # calls JSON.parse with +object+ and +opts+ (see method #parse):
         | 
| 10 12 | 
             
                #   json = '[0, 1, null]'
         | 
| 11 13 | 
             
                #   JSON[json]# => [0, 1, nil]
         | 
| 12 14 | 
             
                #
         | 
| 13 | 
            -
                # Otherwise, calls JSON.generate with +object+ and +opts | 
| 15 | 
            +
                # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
         | 
| 14 16 | 
             
                #   ruby = [0, 1, nil]
         | 
| 15 17 | 
             
                #   JSON[ruby] # => '[0,1,null]'
         | 
| 16 18 | 
             
                def [](object, opts = {})
         | 
| @@ -69,22 +71,30 @@ module JSON | |
| 69 71 | 
             
                  end
         | 
| 70 72 | 
             
                  self.state = generator::State
         | 
| 71 73 | 
             
                  const_set :State, self.state
         | 
| 72 | 
            -
                  const_set :SAFE_STATE_PROTOTYPE, State.new
         | 
| 73 | 
            -
                  const_set :FAST_STATE_PROTOTYPE,  | 
| 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(
         | 
| 74 83 | 
             
                    :indent         => '',
         | 
| 75 84 | 
             
                    :space          => '',
         | 
| 76 85 | 
             
                    :object_nl      => "",
         | 
| 77 86 | 
             
                    :array_nl       => "",
         | 
| 78 87 | 
             
                    :max_nesting    => false
         | 
| 79 88 | 
             
                  )
         | 
| 80 | 
            -
             | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                def create_pretty_state
         | 
| 92 | 
            +
                  State.new(
         | 
| 81 93 | 
             
                    :indent         => '  ',
         | 
| 82 94 | 
             
                    :space          => ' ',
         | 
| 83 95 | 
             
                    :object_nl      => "\n",
         | 
| 84 96 | 
             
                    :array_nl       => "\n"
         | 
| 85 97 | 
             
                  )
         | 
| 86 | 
            -
                ensure
         | 
| 87 | 
            -
                  $VERBOSE = old
         | 
| 88 98 | 
             
                end
         | 
| 89 99 |  | 
| 90 100 | 
             
                # Returns the JSON generator module that is used by JSON. This is
         | 
| @@ -96,13 +106,26 @@ module JSON | |
| 96 106 | 
             
                # either JSON::Ext::Generator::State or JSON::Pure::Generator::State:
         | 
| 97 107 | 
             
                #   JSON.state # => JSON::Ext::Generator::State
         | 
| 98 108 | 
             
                attr_accessor :state
         | 
| 109 | 
            +
              end
         | 
| 110 | 
            +
             | 
| 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
         | 
| 99 123 |  | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                 | 
| 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
         | 
| 104 128 | 
             
              end
         | 
| 105 | 
            -
              self.create_id = 'json_class'
         | 
| 106 129 |  | 
| 107 130 | 
             
              NaN           = 0.0/0
         | 
| 108 131 |  | 
| @@ -144,15 +167,12 @@ module JSON | |
| 144 167 | 
             
              # :call-seq:
         | 
| 145 168 | 
             
              #   JSON.parse(source, opts) -> object
         | 
| 146 169 | 
             
              #
         | 
| 147 | 
            -
              #  | 
| 148 | 
            -
              # {String-convertible object}[doc/implicit_conversion_rdoc.html#label-String-Convertible+Objects]
         | 
| 149 | 
            -
              # (implementing +to_str+), and must contain valid \JSON data.
         | 
| 170 | 
            +
              # Returns the Ruby objects created by parsing the given +source+.
         | 
| 150 171 | 
             
              #
         | 
| 151 | 
            -
              # Argument + | 
| 152 | 
            -
              # {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects]
         | 
| 153 | 
            -
              # (implementing +to_hash+).
         | 
| 172 | 
            +
              # Argument +source+ contains the \String to be parsed.
         | 
| 154 173 | 
             
              #
         | 
| 155 | 
            -
              #  | 
| 174 | 
            +
              # Argument +opts+, if given, contains a \Hash of options for the parsing.
         | 
| 175 | 
            +
              # See {Parsing Options}[#module-JSON-label-Parsing+Options].
         | 
| 156 176 | 
             
              #
         | 
| 157 177 | 
             
              # ---
         | 
| 158 178 | 
             
              #
         | 
| @@ -171,91 +191,24 @@ module JSON | |
| 171 191 | 
             
              # For examples of parsing for all \JSON data types, see
         | 
| 172 192 | 
             
              # {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
         | 
| 173 193 | 
             
              #
         | 
| 174 | 
            -
              #  | 
| 175 | 
            -
              #
         | 
| 176 | 
            -
              # | 
| 177 | 
            -
              #  | 
| 178 | 
            -
              #
         | 
| 179 | 
            -
              #  | 
| 180 | 
            -
              # | 
| 181 | 
            -
              # | 
| 182 | 
            -
              # | 
| 183 | 
            -
              # | 
| 184 | 
            -
              #    | 
| 185 | 
            -
              #    | 
| 186 | 
            -
              # Bad value:
         | 
| 187 | 
            -
              #   # Raises TypeError (wrong argument type Symbol (expected Fixnum)):
         | 
| 188 | 
            -
              #   JSON.parse(source, {max_nesting: :foo})
         | 
| 189 | 
            -
              #
         | 
| 190 | 
            -
              # ---
         | 
| 191 | 
            -
              #
         | 
| 192 | 
            -
              # Option +allow_nan+ (boolean) specifies whether to allow
         | 
| 193 | 
            -
              # NaN, Infinity, and MinusInfinity in +source+;
         | 
| 194 | 
            -
              # defaults to +false+.
         | 
| 195 | 
            -
              #
         | 
| 196 | 
            -
              # With the default, +false+:
         | 
| 197 | 
            -
              #   # Raises JSON::ParserError (225: unexpected token at '[NaN]'):
         | 
| 198 | 
            -
              #   JSON.parse('[NaN]')
         | 
| 199 | 
            -
              #   # Raises JSON::ParserError (232: unexpected token at '[Infinity]'):
         | 
| 200 | 
            -
              #   JSON.parse('[Infinity]')
         | 
| 201 | 
            -
              #   # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'):
         | 
| 202 | 
            -
              #   JSON.parse('[-Infinity]')
         | 
| 203 | 
            -
              # Allow:
         | 
| 204 | 
            -
              #   source = '[NaN, Infinity, -Infinity]'
         | 
| 205 | 
            -
              #   ruby = JSON.parse(source, {allow_nan: true})
         | 
| 206 | 
            -
              #   ruby # => [NaN, Infinity, -Infinity]
         | 
| 207 | 
            -
              #
         | 
| 208 | 
            -
              # ====== Output Options
         | 
| 209 | 
            -
              #
         | 
| 210 | 
            -
              # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
         | 
| 211 | 
            -
              # should be Symbols;
         | 
| 212 | 
            -
              # defaults to +false+ (use Strings).
         | 
| 213 | 
            -
              #
         | 
| 214 | 
            -
              # With the default, +false+:
         | 
| 215 | 
            -
              #   source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
         | 
| 216 | 
            -
              #   ruby = JSON.parse(source)
         | 
| 217 | 
            -
              #   ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
         | 
| 218 | 
            -
              # Use Symbols:
         | 
| 219 | 
            -
              #   ruby = JSON.parse(source, {symbolize_names: true})
         | 
| 220 | 
            -
              #   ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
         | 
| 221 | 
            -
              #
         | 
| 222 | 
            -
              # ---
         | 
| 223 | 
            -
              #
         | 
| 224 | 
            -
              # Option +object_class+ (\Class) specifies the Ruby class to be used
         | 
| 225 | 
            -
              # for each \JSON object;
         | 
| 226 | 
            -
              # defaults to \Hash.
         | 
| 227 | 
            -
              #
         | 
| 228 | 
            -
              # With the default, \Hash:
         | 
| 229 | 
            -
              #   source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
         | 
| 230 | 
            -
              #   ruby = JSON.parse(source)
         | 
| 231 | 
            -
              #   ruby.class # => Hash
         | 
| 232 | 
            -
              # Use class \OpenStruct:
         | 
| 233 | 
            -
              #   ruby = JSON.parse(source, {object_class: OpenStruct})
         | 
| 234 | 
            -
              #   ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
         | 
| 235 | 
            -
              #
         | 
| 236 | 
            -
              # ---
         | 
| 237 | 
            -
              #
         | 
| 238 | 
            -
              # Option +array_class+ (\Class) specifies the Ruby class to be used
         | 
| 239 | 
            -
              # for each \JSON array;
         | 
| 240 | 
            -
              # defaults to \Array.
         | 
| 241 | 
            -
              #
         | 
| 242 | 
            -
              # With the default, \Array:
         | 
| 243 | 
            -
              #   source = '["foo", 1.0, true, false, null]'
         | 
| 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
         | 
| 244 206 | 
             
              #   ruby = JSON.parse(source)
         | 
| 245 | 
            -
              #   ruby | 
| 246 | 
            -
              # Use class \Set:
         | 
| 247 | 
            -
              #   ruby = JSON.parse(source, {array_class: Set})
         | 
| 248 | 
            -
              #   ruby # => #<Set: {"foo", 1.0, true, false, nil}>
         | 
| 207 | 
            +
              #   ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
         | 
| 249 208 | 
             
              #
         | 
| 250 209 | 
             
              # ---
         | 
| 251 210 | 
             
              #
         | 
| 252 | 
            -
              # Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
         | 
| 253 | 
            -
              # See {\JSON Additions}[#module-JSON-label-JSON+Additions].
         | 
| 254 | 
            -
              #
         | 
| 255 | 
            -
              # ====== Exceptions
         | 
| 256 | 
            -
              #
         | 
| 257 211 | 
             
              # Raises an exception if +source+ is not valid JSON:
         | 
| 258 | 
            -
              #
         | 
| 259 212 | 
             
              #   # Raises JSON::ParserError (783: unexpected token at ''):
         | 
| 260 213 | 
             
              #   JSON.parse('')
         | 
| 261 214 | 
             
              #
         | 
| @@ -283,30 +236,47 @@ module JSON | |
| 283 236 | 
             
              end
         | 
| 284 237 |  | 
| 285 238 | 
             
              # :call-seq:
         | 
| 286 | 
            -
              #   JSON. | 
| 239 | 
            +
              #   JSON.load_file(path, opts={}) -> object
         | 
| 287 240 | 
             
              #
         | 
| 288 | 
            -
              #  | 
| 241 | 
            +
              # Calls:
         | 
| 242 | 
            +
              #   parse(File.read(path), opts)
         | 
| 289 243 | 
             
              #
         | 
| 290 | 
            -
              #  | 
| 291 | 
            -
               | 
| 292 | 
            -
             | 
| 244 | 
            +
              # See method #parse.
         | 
| 245 | 
            +
              def load_file(filespec, opts = {})
         | 
| 246 | 
            +
                parse(File.read(filespec), opts)
         | 
| 247 | 
            +
              end
         | 
| 248 | 
            +
             | 
| 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
         | 
| 293 262 | 
             
              #
         | 
| 294 263 | 
             
              # Returns a \String containing the generated \JSON data.
         | 
| 295 264 | 
             
              #
         | 
| 296 265 | 
             
              # See also JSON.fast_generate, JSON.pretty_generate.
         | 
| 297 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 | 
            +
              #
         | 
| 298 272 | 
             
              # ---
         | 
| 299 273 | 
             
              #
         | 
| 300 | 
            -
              # When +obj+ is an
         | 
| 301 | 
            -
              # {Array-convertible object}[doc/implicit_conversion_rdoc.html#label-Array-Convertible+Objects]
         | 
| 302 | 
            -
              # (implementing +to_ary+), returns a \String containing a \JSON array:
         | 
| 274 | 
            +
              # When +obj+ is an \Array, returns a \String containing a \JSON array:
         | 
| 303 275 | 
             
              #   obj = ["foo", 1.0, true, false, nil]
         | 
| 304 276 | 
             
              #   json = JSON.generate(obj)
         | 
| 305 277 | 
             
              #   json # => '["foo",1.0,true,false,null]'
         | 
| 306 278 | 
             
              #
         | 
| 307 | 
            -
              # When +obj+ is a
         | 
| 308 | 
            -
              # {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash-Convertible+Objects],
         | 
| 309 | 
            -
              # return a \String containing a \JSON object:
         | 
| 279 | 
            +
              # When +obj+ is a \Hash, returns a \String containing a \JSON object:
         | 
| 310 280 | 
             
              #   obj = {foo: 0, bar: 's', baz: :bat}
         | 
| 311 281 | 
             
              #   json = JSON.generate(obj)
         | 
| 312 282 | 
             
              #   json # => '{"foo":0,"bar":"s","baz":"bat"}'
         | 
| @@ -314,98 +284,10 @@ module JSON | |
| 314 284 | 
             
              # For examples of generating from other Ruby objects, see
         | 
| 315 285 | 
             
              # {Generating \JSON from Other Objects}[#module-JSON-label-Generating+JSON+from+Other+Objects].
         | 
| 316 286 | 
             
              #
         | 
| 317 | 
            -
              # ====== Input Options
         | 
| 318 | 
            -
              #
         | 
| 319 | 
            -
              # Option +allow_nan+ (boolean) specifies whether
         | 
| 320 | 
            -
              # +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
         | 
| 321 | 
            -
              # defaults to +false+.
         | 
| 322 | 
            -
              #
         | 
| 323 | 
            -
              # With the default, +false+:
         | 
| 324 | 
            -
              #   # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
         | 
| 325 | 
            -
              #   JSON.generate(JSON::NaN)
         | 
| 326 | 
            -
              #   # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
         | 
| 327 | 
            -
              #   JSON.generate(JSON::Infinity)
         | 
| 328 | 
            -
              #   # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
         | 
| 329 | 
            -
              #   JSON.generate(JSON::MinusInfinity)
         | 
| 330 | 
            -
              #
         | 
| 331 | 
            -
              # Allow:
         | 
| 332 | 
            -
              #   ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity]
         | 
| 333 | 
            -
              #   JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
         | 
| 334 | 
            -
              #
         | 
| 335 | 
            -
              # ---
         | 
| 336 | 
            -
              #
         | 
| 337 | 
            -
              # Option +max_nesting+ (\Integer) specifies the maximum nesting depth
         | 
| 338 | 
            -
              # in +obj+; defaults to +100+.
         | 
| 339 | 
            -
              #
         | 
| 340 | 
            -
              # With the default, +100+:
         | 
| 341 | 
            -
              #   obj = [[[[[[0]]]]]]
         | 
| 342 | 
            -
              #   JSON.generate(obj) # => '[[[[[[0]]]]]]'
         | 
| 343 | 
            -
              #
         | 
| 344 | 
            -
              # Too deep:
         | 
| 345 | 
            -
              #   # Raises JSON::NestingError (nesting of 2 is too deep):
         | 
| 346 | 
            -
              #   JSON.generate(obj, max_nesting: 2)
         | 
| 347 | 
            -
              #
         | 
| 348 | 
            -
              # ====== Output Options
         | 
| 349 | 
            -
              #
         | 
| 350 | 
            -
              # The default formatting options generate the most compact
         | 
| 351 | 
            -
              # \JSON data, all on one line and with no whitespace.
         | 
| 352 | 
            -
              #
         | 
| 353 | 
            -
              # You can use these formatting options to generate
         | 
| 354 | 
            -
              # \JSON data in a more open format, using whitespace.
         | 
| 355 | 
            -
              # See also JSON.pretty_generate.
         | 
| 356 | 
            -
              #
         | 
| 357 | 
            -
              # - Option +array_nl+ (\String) specifies a string (usually a newline)
         | 
| 358 | 
            -
              #   to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
         | 
| 359 | 
            -
              # - Option +object_nl+ (\String) specifies a string (usually a newline)
         | 
| 360 | 
            -
              #   to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
         | 
| 361 | 
            -
              # - Option +indent+ (\String) specifies the string (usually spaces) to be
         | 
| 362 | 
            -
              #   used for indentation; defaults to the empty \String, <tt>''</tt>;
         | 
| 363 | 
            -
              #   defaults to the empty \String, <tt>''</tt>;
         | 
| 364 | 
            -
              #   has no effect unless options +array_nl+ or +object_nl+ specify newlines.
         | 
| 365 | 
            -
              # - Option +space+ (\String) specifies a string (usually a space) to be
         | 
| 366 | 
            -
              #   inserted after the colon in each \JSON object's pair;
         | 
| 367 | 
            -
              #   defaults to the empty \String, <tt>''</tt>.
         | 
| 368 | 
            -
              # - Option +space_before+ (\String) specifies a string (usually a space) to be
         | 
| 369 | 
            -
              #   inserted before the colon in each \JSON object's pair;
         | 
| 370 | 
            -
              #   defaults to the empty \String, <tt>''</tt>.
         | 
| 371 | 
            -
              #
         | 
| 372 | 
            -
              # In this example, +obj+ is used first to generate the shortest
         | 
| 373 | 
            -
              # \JSON data (no whitespace), then again with all formatting options
         | 
| 374 | 
            -
              # specified:
         | 
| 375 | 
            -
              #
         | 
| 376 | 
            -
              #   obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
         | 
| 377 | 
            -
              #   json = JSON.generate(obj)
         | 
| 378 | 
            -
              #   puts 'Compact:', json
         | 
| 379 | 
            -
              #   opts = {
         | 
| 380 | 
            -
              #     array_nl: "\n",
         | 
| 381 | 
            -
              #     object_nl: "\n",
         | 
| 382 | 
            -
              #     indent+: '  ',
         | 
| 383 | 
            -
              #     space_before: ' ',
         | 
| 384 | 
            -
              #     space: ' '
         | 
| 385 | 
            -
              #   }
         | 
| 386 | 
            -
              #   puts 'Open:', JSON.generate(obj, opts)
         | 
| 387 | 
            -
              #
         | 
| 388 | 
            -
              # Output:
         | 
| 389 | 
            -
              #   Compact:
         | 
| 390 | 
            -
              #   {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
         | 
| 391 | 
            -
              #   Open:
         | 
| 392 | 
            -
              #   {
         | 
| 393 | 
            -
              #     "foo" : [
         | 
| 394 | 
            -
              #       "bar",
         | 
| 395 | 
            -
              #       "baz"
         | 
| 396 | 
            -
              #   ],
         | 
| 397 | 
            -
              #     "bat" : {
         | 
| 398 | 
            -
              #       "bam" : 0,
         | 
| 399 | 
            -
              #       "bad" : 1
         | 
| 400 | 
            -
              #     }
         | 
| 401 | 
            -
              #   }
         | 
| 402 | 
            -
              #
         | 
| 403 287 | 
             
              # ---
         | 
| 404 288 | 
             
              #
         | 
| 405 289 | 
             
              # Raises an exception if any formatting option is not a \String.
         | 
| 406 290 | 
             
              #
         | 
| 407 | 
            -
              # ====== Exceptions
         | 
| 408 | 
            -
              #
         | 
| 409 291 | 
             
              # Raises an exception if +obj+ contains circular references:
         | 
| 410 292 | 
             
              #   a = []; b = []; a.push(b); b.push(a)
         | 
| 411 293 | 
             
              #   # Raises JSON::NestingError (nesting of 100 is too deep):
         | 
| @@ -415,7 +297,7 @@ module JSON | |
| 415 297 | 
             
                if State === opts
         | 
| 416 298 | 
             
                  state, opts = opts, nil
         | 
| 417 299 | 
             
                else
         | 
| 418 | 
            -
                  state =  | 
| 300 | 
            +
                  state = State.new
         | 
| 419 301 | 
             
                end
         | 
| 420 302 | 
             
                if opts
         | 
| 421 303 | 
             
                  if opts.respond_to? :to_hash
         | 
| @@ -437,6 +319,9 @@ module JSON | |
| 437 319 | 
             
              module_function :unparse
         | 
| 438 320 | 
             
              # :startdoc:
         | 
| 439 321 |  | 
| 322 | 
            +
              # :call-seq:
         | 
| 323 | 
            +
              #   JSON.fast_generate(obj, opts) -> new_string
         | 
| 324 | 
            +
              #
         | 
| 440 325 | 
             
              # Arguments +obj+ and +opts+ here are the same as
         | 
| 441 326 | 
             
              # arguments +obj+ and +opts+ in JSON.generate.
         | 
| 442 327 | 
             
              #
         | 
| @@ -451,7 +336,7 @@ module JSON | |
| 451 336 | 
             
                if State === opts
         | 
| 452 337 | 
             
                  state, opts = opts, nil
         | 
| 453 338 | 
             
                else
         | 
| 454 | 
            -
                  state =  | 
| 339 | 
            +
                  state = JSON.create_fast_state
         | 
| 455 340 | 
             
                end
         | 
| 456 341 | 
             
                if opts
         | 
| 457 342 | 
             
                  if opts.respond_to? :to_hash
         | 
| @@ -506,7 +391,7 @@ module JSON | |
| 506 391 | 
             
                if State === opts
         | 
| 507 392 | 
             
                  state, opts = opts, nil
         | 
| 508 393 | 
             
                else
         | 
| 509 | 
            -
                  state =  | 
| 394 | 
            +
                  state = JSON.create_pretty_state
         | 
| 510 395 | 
             
                end
         | 
| 511 396 | 
             
                if opts
         | 
| 512 397 | 
             
                  if opts.respond_to? :to_hash
         | 
| @@ -541,20 +426,134 @@ module JSON | |
| 541 426 | 
             
                :create_additions => true,
         | 
| 542 427 | 
             
              }
         | 
| 543 428 |  | 
| 544 | 
            -
              #  | 
| 545 | 
            -
              #  | 
| 546 | 
            -
              # | 
| 547 | 
            -
              #  | 
| 548 | 
            -
              # | 
| 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.
         | 
| 459 | 
            +
              #
         | 
| 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"]}
         | 
| 549 488 | 
             
              #
         | 
| 550 | 
            -
              #  | 
| 551 | 
            -
              # | 
| 552 | 
            -
              #  | 
| 553 | 
            -
              #  | 
| 554 | 
            -
              #  | 
| 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"}>}
         | 
| 555 556 | 
             
              #
         | 
| 556 | 
            -
              # This method is part of the implementation of the load/dump interface of
         | 
| 557 | 
            -
              # Marshal and YAML.
         | 
| 558 557 | 
             
              def load(source, proc = nil, options = {})
         | 
| 559 558 | 
             
                opts = load_default_options.merge options
         | 
| 560 559 | 
             
                if source.respond_to? :to_str
         | 
| @@ -573,7 +572,7 @@ module JSON | |
| 573 572 | 
             
              end
         | 
| 574 573 |  | 
| 575 574 | 
             
              # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
         | 
| 576 | 
            -
              def recurse_proc(result, &proc)
         | 
| 575 | 
            +
              def recurse_proc(result, &proc) # :nodoc:
         | 
| 577 576 | 
             
                case result
         | 
| 578 577 | 
             
                when Array
         | 
| 579 578 | 
             
                  result.each { |x| recurse_proc x, &proc }
         | 
| @@ -593,29 +592,42 @@ module JSON | |
| 593 592 | 
             
                # Sets or returns the default options for the JSON.dump method.
         | 
| 594 593 | 
             
                # Initially:
         | 
| 595 594 | 
             
                #   opts = JSON.dump_default_options
         | 
| 596 | 
            -
                #   opts # => {:max_nesting=>false, :allow_nan=>true}
         | 
| 595 | 
            +
                #   opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
         | 
| 597 596 | 
             
                attr_accessor :dump_default_options
         | 
| 598 597 | 
             
              end
         | 
| 599 598 | 
             
              self.dump_default_options = {
         | 
| 600 599 | 
             
                :max_nesting => false,
         | 
| 601 600 | 
             
                :allow_nan   => true,
         | 
| 601 | 
            +
                :escape_slash => false,
         | 
| 602 602 | 
             
              }
         | 
| 603 603 |  | 
| 604 | 
            -
              #  | 
| 605 | 
            -
              #  | 
| 604 | 
            +
              # :call-seq:
         | 
| 605 | 
            +
              #   JSON.dump(obj, io = nil, limit = nil)
         | 
| 606 606 | 
             
              #
         | 
| 607 | 
            -
              #  | 
| 608 | 
            -
              # was given, the resulting JSON is written to it.
         | 
| 607 | 
            +
              # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result.
         | 
| 609 608 | 
             
              #
         | 
| 610 | 
            -
              #  | 
| 611 | 
            -
              # exception is raised. This argument is similar (but not exactly the
         | 
| 612 | 
            -
              # same!) to the _limit_ argument in Marshal.dump.
         | 
| 609 | 
            +
              # The default options can be changed via method JSON.dump_default_options.
         | 
| 613 610 | 
             
              #
         | 
| 614 | 
            -
              #  | 
| 615 | 
            -
              #  | 
| 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+.
         | 
| 616 615 | 
             
              #
         | 
| 617 | 
            -
              #  | 
| 618 | 
            -
              # | 
| 616 | 
            +
              # ---
         | 
| 617 | 
            +
              #
         | 
| 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\"}"
         | 
| 622 | 
            +
              #
         | 
| 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"}
         | 
| 619 631 | 
             
              def dump(obj, anIO = nil, limit = nil)
         | 
| 620 632 | 
             
                if anIO and limit.nil?
         | 
| 621 633 | 
             
                  anIO = anIO.to_io if anIO.respond_to?(:to_io)
         |