summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/json.rb2
-rw-r--r--lib/json/common.rb189
2 files changed, 168 insertions, 23 deletions
diff --git a/lib/json.rb b/lib/json.rb
index 6bb8224..aeb9774 100644
--- a/lib/json.rb
+++ b/lib/json.rb
@@ -319,7 +319,7 @@ require 'json/common'
# opts = {
# array_nl: "\n",
# object_nl: "\n",
-# indent+: ' ',
+# indent: ' ',
# space_before: ' ',
# space: ' '
# }
diff --git a/lib/json/common.rb b/lib/json/common.rb
index ed4e047..f6230a7 100644
--- a/lib/json/common.rb
+++ b/lib/json/common.rb
@@ -4,13 +4,16 @@ require 'json/generic_object'
module JSON
class << self
+ # :call-seq:
+ # JSON[object] -> new_array or new_string
+ #
# If +object+ is a
- # {String-convertible object}[doc/implicit_conversion_rdoc.html#label-String-Convertible+Objects]
- # (implementing +to_str+), calls JSON.parse with +object+ and +opts+:
+ # {String-convertible object}[doc/implicit_conversion_rdoc.html#label-String-Convertible+Objects],
+ # calls JSON.parse with +object+ and +opts+ (see method #parse):
# json = '[0, 1, null]'
# JSON[json]# => [0, 1, nil]
#
- # Otherwise, calls JSON.generate with +object+ and +opts+:
+ # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
# ruby = [0, 1, nil]
# JSON[ruby] # => '[0,1,null]'
def [](object, opts = {})
@@ -171,10 +174,24 @@ module JSON
# For examples of parsing for all \JSON data types, see
# {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
#
- # ====== Exceptions
+ # Parses nested JSON objects:
+ # source = <<-EOT
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # EOT
+ # ruby = JSON.parse(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
#
- # Raises an exception if +source+ is not valid JSON:
+ # ---
#
+ # Raises an exception if +source+ is not valid JSON:
# # Raises JSON::ParserError (783: unexpected token at ''):
# JSON.parse('')
#
@@ -201,12 +218,24 @@ module JSON
Parser.new(source, **(opts||{})).parse
end
- # Parses the content of a file (see parse method documentation for more information).
+ # :call-seq:
+ # CSV.load_file(path, opts={}) -> object
+ #
+ # Calls:
+ # parse(File.read(path), opts)
+ #
+ # See method #parse.
def load_file(filespec, opts = {})
parse(File.read(filespec), opts)
end
- # Parses the content of a file (see parse! method documentation for more information).
+ # :call-seq:
+ # CSV.load_file!(path, opts = {})
+ #
+ # Calls:
+ # CSV.parse!(File.read(path, opts))
+ #
+ # See method #parse!
def load_file!(filespec, opts = {})
parse!(File.read(filespec), opts)
end
@@ -247,8 +276,6 @@ module JSON
#
# Raises an exception if any formatting option is not a \String.
#
- # ====== Exceptions
- #
# Raises an exception if +obj+ contains circular references:
# a = []; b = []; a.push(b); b.push(a)
# # Raises JSON::NestingError (nesting of 100 is too deep):
@@ -280,6 +307,9 @@ module JSON
module_function :unparse
# :startdoc:
+ # :call-seq:
+ # JSON.fast_generate(obj, opts) -> new_string
+ #
# Arguments +obj+ and +opts+ here are the same as
# arguments +obj+ and +opts+ in JSON.generate.
#
@@ -384,20 +414,135 @@ module JSON
:create_additions => true,
}
- # Load a ruby data structure from a JSON _source_ and return it. A source can
- # either be a string-like object, an IO-like object, or an object responding
- # to the read method. If _proc_ was given, it will be called with any nested
- # Ruby object as an argument recursively in depth first order. To modify the
- # default options pass in the optional _options_ argument as well.
+ # :call-seq:
+ # JSON.load(source, proc = nil, options = {}) -> object
#
- # BEWARE: This method is meant to serialise data from trusted user input,
- # like from your own database server or clients under your control, it could
- # be dangerous to allow untrusted users to pass JSON sources into it. The
- # default options for the parser can be changed via the load_default_options
- # method.
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # - Argument +source+ must be, or be convertible to, a \String:
+ # - If +source+ responds to instance method +to_str+,
+ # <tt>source.to_str</tt> becomes the source.
+ # - If +source+ responds to instance method +to_io+,
+ # <tt>source.to_io.read</tt> becomes the source.
+ # - If +source+ responds to instance method +read+,
+ # <tt>source.read</tt> becomes the source.
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
+ # - Option +allow_blank+ specifies a truthy value.
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
+ # - Otherwise, +source+ remains the source.
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
+ # It will be called recursively with each result (depth-first order).
+ # See details below.
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it.
+ # - Argument +opts+, if given, contains options for the parsing, and must be a
+ # {Hash-convertible object}[doc/implicit_conversion_rdoc.html#label-Hash+Convertible+Objects].
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ # The default options can be changed via method JSON.load_default_options=.
+ #
+ # ---
+ #
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
+ # <tt>parse(source, opts)</tt>; see #parse.
+ #
+ # Source for following examples:
+ # source = <<-EOT
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # EOT
+ #
+ # Load a \String:
+ # ruby = JSON.load(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load an \IO object:
+ # require 'stringio'
+ # object = JSON.load(StringIO.new(source))
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load a \File object:
+ # path = 't.json'
+ # File.write(path, source)
+ # File.open(path) do |file|
+ # JSON.load(file)
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # When +proc+ is given:
+ # - Modifies +source+ as above.
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
+ # - Recursively calls <tt>proc(result)</tt>.
+ # - Returns the final result.
+ #
+ # Example:
+ # require 'json'
+ #
+ # # Some classes for the example.
+ # class Base
+ # def initialize(attributes)
+ # @attributes = attributes
+ # end
+ # end
+ # class User < Base; end
+ # class Account < Base; end
+ # class Admin < Base; end
+ # # The JSON source.
+ # json = <<-EOF
+ # {
+ # "users": [
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
+ # {"type": "User", "username": "john", "email": "john@example.com"}
+ # ],
+ # "accounts": [
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
+ # ],
+ # "admins": {"type": "Admin", "password": "0wn3d"}
+ # }
+ # EOF
+ # # Deserializer method.
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
+ # type = obj.is_a?(Hash) && obj["type"]
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
+ # end
+ # # Call to JSON.load
+ # ruby = JSON.load(json, proc {|obj|
+ # case obj
+ # when Hash
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
+ # when Array
+ # obj.map! {|v| deserialize_obj v }
+ # end
+ # })
+ # pp ruby
+ # Output:
+ # {"users"=>
+ # [#<User:0x00000000064c4c98
+ # @attributes=
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
+ # #<User:0x00000000064c4bd0
+ # @attributes=
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
+ # "accounts"=>
+ # [{"account"=>
+ # #<Account:0x00000000064c4928
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
+ # {"account"=>
+ # #<Account:0x00000000064c4680
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
+ # "admins"=>
+ # #<Admin:0x00000000064c41f8
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
#
- # This method is part of the implementation of the load/dump interface of
- # Marshal and YAML.
def load(source, proc = nil, options = {})
opts = load_default_options.merge options
if source.respond_to? :to_str
@@ -416,7 +561,7 @@ module JSON
end
# Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
- def recurse_proc(result, &proc)
+ def recurse_proc(result, &proc) # :nodoc:
case result
when Array
result.each { |x| recurse_proc x, &proc }