GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing docs.ruby-lang.org — module JSON - Documentation for Ruby 3.4 module JSONJavaScript Object Notation (JSON)¶ ↑JSON is a lightweight data-interchange format. A JSON value is one of the following:
A JSON array or object may contain nested arrays, objects, and scalars to any depth: {"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
[{"foo": 0, "bar": 1}, ["baz", 2]]
Using Module JSON¶ ↑To make module JSON available in your code, begin with: require 'json' All examples here assume that this has been done. Parsing JSON¶ ↑You can parse a String containing JSON data using either of two methods: where
The difference between the two methods is that Parsing JSON Arrays¶ ↑When json = '["foo", 1, 1.0, 2.0e2, true, false, null]' ruby = JSON.parse(json) ruby # => ["foo", 1, 1.0, 200.0, true, false, nil] ruby.class # => Array The JSON array may contain nested arrays, objects, and scalars to any depth: json = '[{"foo": 0, "bar": 1}, ["baz", 2]]' JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]] Parsing JSON Objects¶ ↑When the source is a JSON object, json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}' ruby = JSON.parse(json) ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil} ruby.class # => Hash The JSON object may contain nested arrays, objects, and scalars to any depth: json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}' JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]} Parsing JSON Scalars¶ ↑When the source is a JSON scalar (not an array or object), String: ruby = JSON.parse('"foo"') ruby # => 'foo' ruby.class # => String Integer: ruby = JSON.parse('1') ruby # => 1 ruby.class # => Integer Float: ruby = JSON.parse('1.0') ruby # => 1.0 ruby.class # => Float ruby = JSON.parse('2.0e2') ruby # => 200 ruby.class # => Float Boolean: ruby = JSON.parse('true') ruby # => true ruby.class # => TrueClass ruby = JSON.parse('false') ruby # => false ruby.class # => FalseClass Null: ruby = JSON.parse('null') ruby # => nil ruby.class # => NilClass Parsing Options¶ ↑Input Options¶ ↑Option With the default, source = '[0, [1, [2, [3]]]]' ruby = JSON.parse(source) ruby # => [0, [1, [2, [3]]]] Too deep: # Raises JSON::NestingError (nesting of 2 is too deep): JSON.parse(source, {max_nesting: 1}) Bad value: # Raises TypeError (wrong argument type Symbol (expected Fixnum)): JSON.parse(source, {max_nesting: :foo}) Option With the default, # Raises JSON::ParserError (225: unexpected token at '[NaN]'): JSON.parse('[NaN]') # Raises JSON::ParserError (232: unexpected token at '[Infinity]'): JSON.parse('[Infinity]') # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'): JSON.parse('[-Infinity]') Allow: source = '[NaN, Infinity, -Infinity]' ruby = JSON.parse(source, {allow_nan: true}) ruby # => [NaN, Infinity, -Infinity] Output Options¶ ↑Option With the default, 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} Use Symbols: ruby = JSON.parse(source, {symbolize_names: true}) ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil} Option With the default, Hash: source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}' ruby = JSON.parse(source) ruby.class # => Hash Use class OpenStruct: ruby = JSON.parse(source, {object_class: OpenStruct}) ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil> Option With the default, Array: source = '["foo", 1.0, true, false, null]' ruby = JSON.parse(source) ruby.class # => Array Use class Set: ruby = JSON.parse(source, {array_class: Set}) ruby # => #<Set: {"foo", 1.0, true, false, nil}> Option Generating JSON¶ ↑To generate a Ruby String containing JSON data, use method
Generating JSON from Arrays¶ ↑When the source is a Ruby Array, ruby = [0, 's', :foo] json = JSON.generate(ruby) json # => '[0,"s","foo"]' The Ruby Array array may contain nested arrays, hashes, and scalars to any depth: ruby = [0, [1, 2], {foo: 3, bar: 4}] json = JSON.generate(ruby) json # => '[0,[1,2],{"foo":3,"bar":4}]' Generating JSON from Hashes¶ ↑When the source is a Ruby Hash, ruby = {foo: 0, bar: 's', baz: :bat} json = JSON.generate(ruby) json # => '{"foo":0,"bar":"s","baz":"bat"}' The Ruby Hash array may contain nested arrays, hashes, and scalars to any depth: ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad} json = JSON.generate(ruby) json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}' Generating JSON from Other Objects¶ ↑When the source is neither an Array nor a Hash, the generated JSON data depends on the class of the source. When the source is a Ruby Integer or Float, JSON.generate(42) # => '42' JSON.generate(0.42) # => '0.42' When the source is a Ruby String, JSON.generate('A string') # => '"A string"' When the source is JSON.generate(true) # => 'true' JSON.generate(false) # => 'false' JSON.generate(nil) # => 'null' When the source is none of the above, JSON.generate(:foo) # => '"foo"' JSON.generate(Complex(0, 0)) # => '"0+0i"' JSON.generate(Dir.new('.')) # => '"#<Dir>"' Generating Options¶ ↑Input Options¶ ↑Option With the default, # Raises JSON::GeneratorError (920: NaN not allowed in JSON): JSON.generate(JSON::NaN) # Raises JSON::GeneratorError (917: Infinity not allowed in JSON): JSON.generate(JSON::Infinity) # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON): JSON.generate(JSON::MinusInfinity) Allow: ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity] JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]' Option With the default, obj = [[[[[[0]]]]]] JSON.generate(obj) # => '[[[[[[0]]]]]]' Too deep: # Raises JSON::NestingError (nesting of 2 is too deep): JSON.generate(obj, max_nesting: 2) Escaping Options¶ ↑Options Options Output Options¶ ↑The default formatting options generate the most compact JSON data, all on one line and with no whitespace. You can use these formatting options to generate JSON data in a more open format, using whitespace. See also
In this example, obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} json = JSON.generate(obj) puts 'Compact:', json opts = { array_nl: "\n", object_nl: "\n", indent: ' ', space_before: ' ', space: ' ' } puts 'Open:', JSON.generate(obj, opts) Output: Compact:
{"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
Open:
{
"foo" : [
"bar",
"baz"
],
"bat" : {
"bam" : 0,
"bad" : 1
}
}
JSON Additions¶ ↑When you “round trip” a non-String object from Ruby to JSON and back, you have a new String, instead of the object you began with: ruby0 = Range.new(0, 2) json = JSON.generate(ruby0) json # => '0..2"' ruby1 = JSON.parse(json) ruby1 # => '0..2' ruby1.class # => String You can use JSON additions to preserve the original object. The addition is an extension of a ruby class, so that:
This example shows a Range being generated into JSON and parsed back into Ruby, both without and with the addition for Range: ruby = Range.new(0, 2) # This passage does not use the addition for Range. json0 = JSON.generate(ruby) ruby0 = JSON.parse(json0) # This passage uses the addition for Range. require 'json/add/range' json1 = JSON.generate(ruby) ruby1 = JSON.parse(json1, create_additions: true) # Make a nice display. display = <<~EOT Generated JSON: Without addition: #{json0} (#{json0.class}) With addition: #{json1} (#{json1.class}) Parsed JSON: Without addition: #{ruby0.inspect} (#{ruby0.class}) With addition: #{ruby1.inspect} (#{ruby1.class}) EOT puts display This output shows the different results: Generated JSON:
Without addition: "0..2" (String)
With addition: {"json_class":"Range","a":[0,2,false]} (String)
Parsed JSON:
Without addition: "0..2" (String)
With addition: 0..2 (Range)
The JSON module includes additions for certain classes. You can also craft custom additions. See Custom JSON Additions. Built-in Additions¶ ↑The JSON module includes additions for certain classes. To use an addition,
To reduce punctuation clutter, the examples below show the generated JSON via BigDecimal: require 'json/add/bigdecimal' ruby0 = BigDecimal(0) # 0.0 json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"} ruby1 = JSON.parse(json, create_additions: true) # 0.0 ruby1.class # => BigDecimal Complex: require 'json/add/complex' ruby0 = Complex(1+0i) # 1+0i json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0} ruby1 = JSON.parse(json, create_additions: true) # 1+0i ruby1.class # Complex Date: require 'json/add/date' ruby0 = Date.today # 2020-05-02 json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 ruby1.class # Date DateTime: require 'json/add/date_time' ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00 json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0} ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00 ruby1.class # DateTime Exception (and its subclasses including RuntimeError): require 'json/add/exception' ruby0 = Exception.new('A message') # A message json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null} ruby1 = JSON.parse(json, create_additions: true) # A message ruby1.class # Exception ruby0 = RuntimeError.new('Another message') # Another message json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null} ruby1 = JSON.parse(json, create_additions: true) # Another message ruby1.class # RuntimeError OpenStruct: require 'json/add/ostruct' ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby"> json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}} ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby"> ruby1.class # OpenStruct Range: require 'json/add/range' ruby0 = Range.new(0, 2) # 0..2 json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]} ruby1 = JSON.parse(json, create_additions: true) # 0..2 ruby1.class # Range Rational: require 'json/add/rational' ruby0 = Rational(1, 3) # 1/3 json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3} ruby1 = JSON.parse(json, create_additions: true) # 1/3 ruby1.class # Rational Regexp: require 'json/add/regexp' ruby0 = Regexp.new('foo') # (?-mix:foo) json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"} ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo) ruby1.class # Regexp Set: require 'json/add/set' ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}> json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]} ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}> ruby1.class # Set Struct: require 'json/add/struct' Customer = Struct.new(:name, :address) # Customer ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main"> json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]} ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main"> ruby1.class # Customer 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 class Foo attr_accessor :bar, :baz def initialize(bar, baz) self.bar = bar 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' => [ bar, 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)
Sets or returns the default options for the opts = JSON.dump_default_options opts # => {:max_nesting=>false, :allow_nan=>true} Sets or returns default options for the opts = JSON.load_default_options opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} Sets or returns default options for the opts = JSON.load_default_options opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} Source# File ext/json/lib/json/common.rb, line 23 def [](object, opts = {}) if object.is_a?(String) return JSON.parse(object, opts) elsif object.respond_to?(:to_str) str = object.to_str if str.is_a?(String) return JSON.parse(str, opts) end end JSON.generate(object, opts) end If json = '[0, 1, null]' JSON[json]# => [0, 1, nil] Otherwise, calls ruby = [0, 1, nil] JSON[ruby] # => '[0,1,null]' Source# File ext/json/lib/json/common.rb, line 80 def create_fast_state State.new( :indent => '', :space => '', :object_nl => "", :array_nl => "", :max_nesting => false ) end Source# File ext/json/lib/json/common.rb, line 115 def self.create_id Thread.current[:"JSON.create_id"] || 'json_class' end Returns the current create identifier. See also Source# File ext/json/lib/json/common.rb, line 109 def self.create_id=(new_value) Thread.current[:"JSON.create_id"] = new_value.dup.freeze end Sets create identifier, which is used to decide if the json_create hook of a class should be called; initial value is JSON.create_id # => 'json_class' Source# File ext/json/lib/json/common.rb, line 90 def create_pretty_state State.new( :indent => ' ', :space => ' ', :object_nl => "\n", :array_nl => "\n" ) end Source# File ext/json/lib/json/common.rb, line 832 def self.iconv(to, from, string) string.encode(to, from) end Encodes string using Source# File ext/json/lib/json/common.rb, line 795 def dump(obj, anIO = nil, limit = nil, kwargs = nil) if kwargs.nil? if limit.nil? if anIO.is_a?(Hash) kwargs = anIO anIO = nil end elsif limit.is_a?(Hash) kwargs = limit limit = nil end end unless anIO.nil? if anIO.respond_to?(:to_io) anIO = anIO.to_io elsif limit.nil? && !anIO.respond_to?(:write) anIO, limit = nil, anIO end end opts = JSON.dump_default_options opts = opts.merge(:max_nesting => limit) if limit opts = merge_dump_options(opts, **kwargs) if kwargs begin if State === opts opts.generate(obj, anIO) else State.generate(obj, opts, anIO) end rescue JSON::NestingError raise ArgumentError, "exceed depth limit" end end Dumps The default options can be changed via method
When argument 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 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"}
Source# File ext/json/lib/json/common.rb, line 329 def fast_generate(obj, opts = nil) if State === opts state = opts else state = JSON.create_fast_state.configure(opts) end state.generate(obj) end Arguments By default, generates JSON data without checking for circular references in Raises an exception if a = []; b = []; a.push(b); b.push(a) # Raises SystemStackError (stack level too deep): JSON.fast_generate(a) Source# File ext/json/lib/json/common.rb, line 301 def generate(obj, opts = nil) if State === opts opts.generate(obj) else State.generate(obj, opts, nil) end end Returns a String containing the generated JSON data. See also Argument Argument When obj = ["foo", 1.0, true, false, nil] json = JSON.generate(obj) json # => '["foo",1.0,true,false,null]' When 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 a = []; b = []; a.push(b); b.push(a) # Raises JSON::NestingError (nesting of 100 is too deep): JSON.generate(a) Source# File ext/json/lib/json/common.rb, line 714 def load(source, proc = nil, options = nil) opts = if options.nil? load_default_options else load_default_options.merge(options) end unless source.is_a?(String) 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 end if opts[:allow_blank] && (source.nil? || source.empty?) source = 'null' end result = parse(source, opts) recurse_proc(result, &proc) if proc result end Returns the Ruby objects created by parsing the given 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 Since
When no Source for following examples: source = <<~JSON { "name": "Dave", "age" :40, "hats": [ "Cattleman's", "Panama", "Tophat" ] } JSON 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
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": "[email protected]"}, {"type": "User", "username": "john", "email": "[email protected]"} ], "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"=>"[email protected]"}>,
#<User:0x00000000064c4bd0
@attributes=
{"type"=>"User", "username"=>"john", "email"=>"[email protected]"}>],
"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"}>}
Also aliased as: restore
Source# File ext/json/lib/json/common.rb, line 250 def load_file(filespec, opts = nil) parse(File.read(filespec, encoding: Encoding::UTF_8), opts) end Calls: parse(File.read(path), opts) See method Source# File ext/json/lib/json/common.rb, line 261 def load_file!(filespec, opts = {}) parse!(File.read(filespec, encoding: Encoding::UTF_8), opts) end Calls: JSON.parse!(File.read(path, opts)) See method Source# File ext/json/lib/json/common.rb, line 836 def merge_dump_options(opts, strict: NOT_SET) opts = opts.merge(strict: strict) if NOT_SET != strict opts end Source# File ext/json/lib/json/common.rb, line 220 def parse(source, opts = nil) Parser.parse(source, opts) end Returns the Ruby objects created by parsing the given Argument Argument When source = '["foo", 1.0, true, false, null]' ruby = JSON.parse(source) ruby # => ["foo", 1.0, true, false, nil] ruby.class # => Array When 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 source = <<~JSON { "name": "Dave", "age" :40, "hats": [ "Cattleman's", "Panama", "Tophat" ] } JSON ruby = JSON.parse(source) ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} Raises an exception if # Raises JSON::ParserError (783: unexpected token at ''): JSON.parse('') Source# File ext/json/lib/json/common.rb, line 235 def parse!(source, opts = {}) opts = { :max_nesting => false, :allow_nan => true }.merge(opts) Parser.new(source, **(opts||{})).parse end Calls parse(source, opts) with Differences from
Source# File ext/json/lib/json/common.rb, line 374 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 Arguments Default options are: {
indent: ' ', # Two spaces
space: ' ', # One space
array_nl: "\n", # Newline
object_nl: "\n" # Newline
}
Example: obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}} json = JSON.pretty_generate(obj) puts json Output: {
"foo": [
"bar",
"baz"
],
"bat": {
"bam": 0,
"bad": 1
}
}
Source# File ext/json/lib/json/common.rb, line 554 def unsafe_load(source, proc = nil, options = nil) opts = if options.nil? unsafe_load_default_options else unsafe_load_default_options.merge(options) end unless source.is_a?(String) 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 end if opts[:allow_blank] && (source.nil? || source.empty?) source = 'null' end result = parse(source, opts) recurse_proc(result, &proc) if proc result end Returns the Ruby objects created by parsing the given 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
When no Source for following examples: source = <<~JSON { "name": "Dave", "age" :40, "hats": [ "Cattleman's", "Panama", "Tophat" ] } JSON Load a String: ruby = JSON.unsafe_load(source) ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} Load an IO object: require 'stringio' object = JSON.unsafe_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.unsafe_load(file) end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} When
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": "[email protected]"}, {"type": "User", "username": "john", "email": "[email protected]"} ], "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.unsafe_load ruby = JSON.unsafe_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"=>"[email protected]"}>,
#<User:0x00000000064c4bd0
@attributes=
{"type"=>"User", "username"=>"john", "email"=>"[email protected]"}>],
"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"}>}
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |