Module: JSON
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Classes:
| |
Exceptions:
| |
Defined in: | ext/json/lib/json.rb, ext/json/generator/generator.c, ext/json/lib/json/common.rb, ext/json/lib/json/ext.rb, ext/json/lib/json/generic_object.rb, ext/json/lib/json/version.rb, ext/json/parser/parser.c |
Overview
Symbol:
require 'json/add/symbol'
ruby0 = :foo # foo
json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
ruby1 = JSON.parse(json, create_additions: true) # foo
ruby1.class # Symbol
Time:
require 'json/add/time'
ruby0 = Time.now # 2020-05-02 11:28:26 -0500
json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
ruby1.class # Time
Custom JSON Additions
In addition to the JSON additions provided, you can craft JSON additions of your own, either for Ruby built-in classes or for user-defined classes.
Here’s a user-defined class Foo
:
class Foo
attr_accessor :, :baz
def initialize(, baz)
self. =
self.baz = baz
end
end
Here’s the JSON addition for it:
# Extend class Foo with JSON addition.
class Foo
# Serialize Foo object with its class name and arguments
def to_json(*args)
{
JSON.create_id => self.class.name,
'a' => [ , baz ]
}.to_json(*args)
end
# Deserialize JSON string by constructing new Foo object with arguments.
def self.json_create(object)
new(*object['a'])
end
end
Demonstration:
require 'json'
# This Foo object has no custom addition.
foo0 = Foo.new(0, 1)
json0 = JSON.generate(foo0)
obj0 = JSON.parse(json0)
# Lood the custom addition.
require_relative 'foo_addition'
# This foo has the custom addition.
foo1 = Foo.new(0, 1)
json1 = JSON.generate(foo1)
obj1 = JSON.parse(json1, create_additions: true)
# Make a nice display.
display = <<EOT
Generated JSON:
Without custom addition: #{json0} (#{json0.class})
With custom addition: #{json1} (#{json1.class})
Parsed JSON:
Without custom addition: #{obj0.inspect} (#{obj0.class})
With custom addition: #{obj1.inspect} (#{obj1.class})
EOT
puts display
Output:
Generated JSON:
Without custom addition: "#<Foo:0x0000000006534e80>" (String)
With custom addition: {"json_class":"Foo","a":[0,1]} (String)
Parsed JSON:
Without custom addition: "#<Foo:0x0000000006534e80>" (String)
With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
Constant Summary
-
CREATE_ID_TLS_KEY =
private
# File 'ext/json/lib/json/common.rb', line 114"JSON.create_id".freeze
-
DEFAULT_CREATE_ID =
private
# File 'ext/json/lib/json/common.rb', line 111'json_class'.freeze
-
Infinity =
# File 'ext/json/lib/json/common.rb', line 1321.0/0
-
JSON_LOADED =
# File 'ext/json/lib/json/ext.rb', line 14true
-
MinusInfinity =
# File 'ext/json/lib/json/common.rb', line 134-Infinity
-
NaN =
# File 'ext/json/lib/json/common.rb', line 1300.0/0
-
UnparserError =
Internal use only
For backwards compatibility
GeneratorError
-
VERSION =
JSON
version'2.5.1'
-
VERSION_ARRAY =
Internal use only
# File 'ext/json/lib/json/version.rb', line 5VERSION.split(/\./).map { |x| x.to_i }
-
VERSION_BUILD =
Internal use only
# File 'ext/json/lib/json/version.rb', line 8VERSION_ARRAY[2]
-
VERSION_MAJOR =
Internal use only
# File 'ext/json/lib/json/version.rb', line 6VERSION_ARRAY[0]
-
VERSION_MINOR =
Internal use only
# File 'ext/json/lib/json/version.rb', line 7VERSION_ARRAY[1]
Class Attribute Summary
-
.create_id
rw
Returns the current create identifier.
-
.create_id=(new_value)
rw
Sets create identifier, which is used to decide if the json_create hook of a class should be called; initial value is
json_class
: -
.dump_default_options
rw
Sets or returns the default options for the .dump method.
-
.generator
rw
Returns the
JSON
generator module that is used byJSON
. -
.load_default_options
rw
Sets or returns default options for the .load method.
-
.parser
rw
Returns the
JSON
parser class that is used byJSON
. -
.state
rw
Sets or Returns the
JSON
generator state class that is used byJSON
. -
.generator=(generator)
rw
Internal use only
::Set
the module generator to be used byJSON
. -
.parser=(parser)
rw
Internal use only
::Set
theJSON
parser class parser to be used byJSON
.
Class Method Summary
- .[](object) ⇒ Array, String
- .create_fast_state
- .create_pretty_state
-
.iconv(to, from, string)
Encodes string using
String.encode
. -
.dump(obj, io = nil, limit = nil)
mod_func
Dumps
obj
as a JSON string, i.e. calls generate on the object and returns the result. -
.fast_generate(obj, opts) ⇒ String
(also: .fast_unparse)
mod_func
Arguments
obj
andopts
here are the same as argumentsobj
andopts
in .generate. - .fast_unparse mod_func
-
.generate(obj, opts = nil) ⇒ String
(also: .unparse)
mod_func
Returns a String containing the generated JSON data.
-
.load(source, proc = nil, options = {}) ⇒ Object
(also: .restore)
mod_func
Returns the Ruby objects created by parsing the given
source
. -
.load_file(path, opts = {}) ⇒ Object
mod_func
Calls:
-
.load_file!(path, opts = {})
mod_func
Calls:
-
.parse(source, opts) ⇒ Object
mod_func
Returns the Ruby objects created by parsing the given
source
. -
.parse!(source, opts) ⇒ Object
mod_func
Calls.
-
.pretty_generate(obj, opts = nil) ⇒ String
(also: .pretty_unparse)
mod_func
Arguments
obj
andopts
here are the same as argumentsobj
andopts
in .generate. - .pretty_unparse mod_func
- .restore mod_func
- .unparse mod_func
-
.deep_const_get(path)
Internal use only
Return the constant located at path.
-
.recurse_proc(result, &proc)
mod_func
Internal use only
Recursively calls passed Proc if the parsed data structure is an Array or Hash.
Class Attribute Details
.create_id (rw)
Returns the current create identifier. See also .create_id=.
# File 'ext/json/lib/json/common.rb', line 126
def self.create_id Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID end
.create_id=(new_value) (rw)
Sets create identifier, which is used to decide if the json_create hook of a class should be called; initial value is json_class
:
JSON.create_id # => 'json_class'
# File 'ext/json/lib/json/common.rb', line 120
def self.create_id=(new_value) Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze end
.dump_default_options (rw)
Sets or returns the default options for the .dump method. Initially:
opts = JSON.
opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
# File 'ext/json/lib/json/common.rb', line 596
attr_accessor :
.generator (rw)
Returns the JSON
generator module that is used by JSON
. This is either ::JSON::Ext::Generator
or JSON::Pure::Generator
:
JSON.generator # => JSON::Ext::Generator
# File 'ext/json/lib/json/common.rb', line 103
attr_reader :generator
.generator=(generator) (rw)
::Set
the module generator to be used by JSON
.
# File 'ext/json/lib/json/common.rb', line 58
def generator=(generator) # :nodoc: old, $VERBOSE = $VERBOSE, nil @generator = generator generator_methods = generator::GeneratorMethods for const in generator_methods.constants klass = deep_const_get(const) modul = generator_methods.const_get(const) klass.class_eval do instance_methods(false).each do |m| m.to_s == 'to_json' and remove_method m end include modul end end self.state = generator::State const_set :State, self.state const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby const_set :FAST_STATE_PROTOTYPE, create_fast_state const_set :PRETTY_STATE_PROTOTYPE, create_pretty_state ensure $VERBOSE = old end
.load_default_options (rw)
Sets or returns default options for the .load method. Initially:
opts = JSON.
opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
# File 'ext/json/lib/json/common.rb', line 420
attr_accessor :
.parser (rw)
Returns the JSON
parser class that is used by JSON
. This is either ::JSON::Ext::Parser
or JSON::Pure::Parser
:
JSON.parser # => JSON::Ext::Parser
# File 'ext/json/lib/json/common.rb', line 29
attr_reader :parser
.parser=(parser) (rw)
::Set
the JSON
parser class parser to be used by JSON
.
.state (rw)
Sets or Returns the JSON
generator state class that is used by JSON
. This is either ::JSON::Ext::Generator::State
or JSON::Pure::Generator::State
:
JSON.state # => JSON::Ext::Generator::State
# File 'ext/json/lib/json/common.rb', line 108
attr_accessor :state
Class Method Details
.[](object) ⇒ Array
, String
.create_fast_state
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 81
def create_fast_state State.new( :indent => '', :space => '', :object_nl => "", :array_nl => "", :max_nesting => false ) end
.create_pretty_state
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 91
def create_pretty_state State.new( :indent => ' ', :space => ' ', :object_nl => "\n", :array_nl => "\n" ) end
.deep_const_get(path)
Return the constant located at path. The format of path has to be either ::A::B::C or A::B::C
. In any case, A has to be located at the top level (absolute namespace path?). If there doesn’t exist a constant at the given path, an ArgumentError is raised.
# File 'ext/json/lib/json/common.rb', line 42
def deep_const_get(path) # :nodoc: path.to_s.split(/::/).inject(Object) do |p, c| case when c.empty? then p when p.const_defined?(c, true) then p.const_get(c) else begin p.const_missing(c) rescue NameError => e raise ArgumentError, "can't get const #{path}: #{e}" end end end end
.dump(obj, io = nil, limit = nil) (mod_func)
Dumps obj
as a JSON string, i.e. calls generate on the object and returns the result.
The default options can be changed via method .dump_default_options.
-
Argument
io
, if given, should respond to methodwrite
; the JSON String is written toio
, andio
is returned. Ifio
is not given, the JSON String is returned. -
Argument
limit
, if given, is passed to .generate as optionmax_nesting
.
When argument io
is not given, returns the JSON String generated from obj
:
obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
json = JSON.dump(obj)
json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}"
When argument io
is given, writes the JSON String to io
and returns io
:
path = 't.json'
File.open(path, 'w') do |file|
JSON.dump(obj, file)
end # => #<File:t.json (closed)>
puts File.read(path)
Output:
{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
# File 'ext/json/lib/json/common.rb', line 631
def dump(obj, anIO = nil, limit = nil) if anIO and limit.nil? anIO = anIO.to_io if anIO.respond_to?(:to_io) unless anIO.respond_to?(:write) limit = anIO anIO = nil end end opts = JSON. opts = opts.merge(:max_nesting => limit) if limit result = generate(obj, opts) if anIO anIO.write result anIO else result end rescue JSON::NestingError raise ArgumentError, "exceed depth limit" end
.fast_generate(obj, opts) ⇒ String
(mod_func) Also known as: .fast_unparse
Arguments obj
and opts
here are the same as arguments obj
and opts
in .generate.
By default, generates JSON data without checking for circular references in obj
(option max_nesting
set to false
, disabled).
Raises an exception if obj
contains circular references:
a = []; b = []; a.push(b); b.push(a)
# Raises SystemStackError (stack level too deep):
JSON.fast_generate(a)
# File 'ext/json/lib/json/common.rb', line 335
def fast_generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = JSON.create_fast_state end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state.configure(opts) end state.generate(obj) end
.fast_unparse (mod_func)
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 356
alias fast_unparse fast_generate
.generate(obj, opts = nil) ⇒ String
(mod_func) Also known as: .unparse
Returns a String containing the generated JSON data.
See also .fast_generate, .pretty_generate.
Argument obj
is the Ruby object to be converted to JSON.
Argument opts
, if given, contains a Hash of options for the generation. See Generating Options.
When obj
is an Array, returns a String containing a JSON array:
obj = ["foo", 1.0, true, false, nil]
json = JSON.generate(obj)
json # => '["foo",1.0,true,false,null]'
When obj
is a Hash, returns a String containing a JSON object:
obj = {foo: 0, bar: 's', baz: :bat}
json = JSON.generate(obj)
json # => '{"foo":0,"bar":"s","baz":"bat"}'
For examples of generating from other Ruby objects, see Generating JSON from Other Objects.
Raises an exception if any formatting option is not a String.
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):
JSON.generate(a)
# File 'ext/json/lib/json/common.rb', line 296
def generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = State.new end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state = state.configure(opts) end state.generate(obj) end
.iconv(to, from, string)
Encodes string using String.encode
.
# File 'ext/json/lib/json/common.rb', line 653
def self.iconv(to, from, string) string.encode(to, from) end
.load(source, proc = nil, options = {}) ⇒ Object (mod_func) Also known as: .restore
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 methodto_str
,source.to_str
becomes the source. -
If
source
responds to instance methodto_io
,source.to_io.read
becomes the source. -
If
source
responds to instance methodread
,source.read
becomes the source. -
If both of the following are true, source becomes the String
'null'
:-
Option
allow_blank
specifies a truthy value. -
The source, as defined above, is
nil
or the empty String''
.
-
-
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 a Hash of options for the parsing. See 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 parse(source, opts)
; 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 callingparse(source, opts)
. -
Recursively calls
proc(result)
. -
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"}>}
# File 'ext/json/lib/json/common.rb', line 557
def load(source, proc = nil, = {}) opts = .merge if source.respond_to? :to_str source = source.to_str elsif source.respond_to? :to_io source = source.to_io.read elsif source.respond_to?(:read) source = source.read end if opts[:allow_blank] && (source.nil? || source.empty?) source = 'null' end result = parse(source, opts) recurse_proc(result, &proc) if proc result end
.load_file(path, opts = {}) ⇒ Object (mod_func)
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 245
def load_file(filespec, opts = {}) parse(File.read(filespec), opts) end
.load_file!(path, opts = {}) (mod_func)
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 256
def load_file!(filespec, opts = {}) parse!(File.read(filespec), opts) end
.parse(source, opts) ⇒ Object (mod_func)
Returns the Ruby objects created by parsing the given source
.
Argument source
contains the String to be parsed.
Argument opts
, if given, contains a Hash of options for the parsing. See Parsing Options.
When source
is a JSON array, returns a Ruby Array:
source = '["foo", 1.0, true, false, null]'
ruby = JSON.parse(source)
ruby # => ["foo", 1.0, true, false, nil]
ruby.class # => Array
When source
is a JSON object, returns a Ruby Hash:
source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
ruby = JSON.parse(source)
ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
ruby.class # => Hash
For examples of parsing for all JSON data types, see Parsing JSON.
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 JSON::ParserError (783: unexpected token at ''):
JSON.parse('')
# File 'ext/json/lib/json/common.rb', line 215
def parse(source, opts = {}) Parser.new(source, **(opts||{})).parse end
.parse!(source, opts) ⇒ Object (mod_func)
# File 'ext/json/lib/json/common.rb', line 230
def parse!(source, opts = {}) opts = { :max_nesting => false, :allow_nan => true }.merge(opts) Parser.new(source, **(opts||{})).parse end
.pretty_generate(obj, opts = nil) ⇒ String
(mod_func) Also known as: .pretty_unparse
Arguments obj
and opts
here are the same as arguments obj
and opts
in .generate.
Default options are:
{
indent: ' ', # Two spaces
space: ' ', # One space
array_nl: "\n", # Newline
object_nl: "\n" # Newline
}
Example:
obj = {foo: [:, :baz], bat: {bam: 0, bad: 1}}
json = JSON.pretty_generate(obj)
puts json
Output:
{
"foo": [
"bar",
"baz"
],
"bat": {
"bam": 0,
"bad": 1
}
}
# File 'ext/json/lib/json/common.rb', line 390
def pretty_generate(obj, opts = nil) if State === opts state, opts = opts, nil else state = JSON.create_pretty_state end if opts if opts.respond_to? :to_hash opts = opts.to_hash elsif opts.respond_to? :to_h opts = opts.to_h else raise TypeError, "can't convert #{opts.class} into Hash" end state.configure(opts) end state.generate(obj) end
.pretty_unparse (mod_func)
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 411
alias pretty_unparse pretty_generate
.recurse_proc(result, &proc) (mod_func)
Recursively calls passed Proc if the parsed data structure is an Array or Hash
# File 'ext/json/lib/json/common.rb', line 575
def recurse_proc(result, &proc) # :nodoc: case result when Array result.each { |x| recurse_proc x, &proc } proc.call result when Hash result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } proc.call result else proc.call result end end
.restore (mod_func)
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 588
alias restore load
.unparse (mod_func)
[ GitHub ]# File 'ext/json/lib/json/common.rb', line 318
alias unparse generate