Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →
JSON#unsafe_load
# File tmp/rubies/ruby-4.1.0-preview1/ext/json/lib/json/common.rb, line 568
def unsafe_load(source, proc = nil, **options)
load(source, proc, max_nesting: false, **options)
end
Returns the Ruby objects created by parsing the given source.
BEWARE: This method is meant to deserialise 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
sourcemust be, or be convertible to, a String:-
If
sourceresponds to instance methodto_str,source.to_strbecomes the source. -
If
sourceresponds to instance methodto_io,source.to_io.readbecomes the source. -
If
sourceresponds to instance methodread,source.readbecomes the source. -
If both of the following are true, source becomes the String
'null':-
Option
allow_blankspecifies a truthy value. -
The source, as defined above, is
nilor the empty String''.
-
-
Otherwise,
sourceremains 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. -
Argument
opts, if given, contains a Hash of options for the parsing. See Parsing 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 = <<~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 proc is given:
-
Modifies
sourceas above. -
Gets the
resultfrom 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": "[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 obj }) 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"}>}