从ruby文档中我可以看到load
方法将proc作为arg而parse
没有。还有其他区别吗?比方说,当我有一个JSON字符串时,我应该使用哪种方法将其转换为Ruby对象?
加载(来源,proc = nil,options = {}) 从JSON源加载ruby数据结构并返回它。源可以是类似于字符串的对象,类似IO的对象,也可以是响应read方法的对象。如果给出了proc,它将以任何嵌套的Ruby对象作为参数以深度优先顺序递归调用。要修改默认选项,也要传递可选选项参数。 此方法是Marshal和YAML的加载/转储接口实现的一部分。 别名为:restore
解析(来源,操作= {}) 将JSON文档源解析为Ruby数据结构并将其返回。
答案 0 :(得分:30)
JSON#parse
将JSON字符串解析为Ruby Hash。
JSON.parse('{"name": "Some Name"}') # => {"name" => "Some Name"}
JSON#load
接受字符串或IO(文件等)并将其转换为Ruby Hash / Array
JSON.load File.new("names.json") # => Reads the JSON inside the file and results in a Ruby Object.
JSON.load '{"name": "Some Name"}' # Works just like #parse
实际上,它会转换响应#read
方法的任何对象。例如:
class A
def initialize
@a = '{"name": "Some Name"}'
end
def read
@a
end
end
JSON.load(A.new) # => {"name" => "Some Name"}
答案 1 :(得分:17)
另一个区别是JSON.load
默认解析单个值(不是对象而不是数组)。
JSON.load("false")
=> false
JSON.load("123")
=> 123
但JSON.parse
要求启用quirks mode
来解析此值。
JSON.parse("false")
JSON::ParserError: 757: unexpected token at 'false'
JSON.parse("false", quirks_mode: true)
=> false
答案 2 :(得分:15)
一个关键的区别是JSON.load
在给定不受信任的输入时是不安全的(使用JSON.parse
可以实现相同,但它有安全的默认值)。这是因为它提供了一种实例化除" normal"之外的类的方法。散列,字符串,数组,数字类:
class Foo
def self.json_creatable?
true
end
def self.json_create attributes
puts "called with #{attributes}"
end
end
JSON.parse('{"json_class": "Foo"}') #=> {"json_class"=>"Foo"}
而
JSON.load('{"json_class": "Foo"}')
called with {"json_class"=>"Foo"}
#=> nil
这是为了实现数据的自定义序列化 - 在解析来自广阔世界的数据时不应该使用它。当然,您需要实现json_creatable?
和json_create
方法才能真正实现任何目标,但您对自己的依赖关系没有做到这一点或以这种方式实现method_missing
有多大的信心它可能被滥用? (例如,参见Marshal.load
漏洞。由于此JSON.load
& JSON.parse
显着收紧了。
在处理不受信任的数据时始终使用JSON.parse
,或者除非您需要JSON.load
的额外功能
答案 3 :(得分:0)
另一个不同之处:不同的选择。
常用示例(注意_keys
与_names
):
JSON.load '{"key": "val"}', symbolize_keys: true
=> {"key" => "val"} # parse option syntax silently ignored
JSON.parse '{"key": "val"}', symbolize_keys: true
=> {:key => "val"} # symbols, yay!
JSON.load '{"key": "val"}', symbolize_names: true
=> {:key => "val"} # using the correct syntax for load
答案 4 :(得分:0)
load
源代码click me
# File ext/json/lib/json/common.rb, line 323
def load(source, proc = nil, options = {})
opts = load_default_options.merge options
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
方法中的第一行:
opts = load_default_options.merge options
我们可以在控制台中调用JSON#load_default_options
:
JSON.load_default_options
=> {:max_nesting=>false, :allow_nan=>true, :quirks_mode=>true, :create_additions=>true}
我们可以看到有四个默认选项,它们的含义是什么,我们可以从这里click me中获取一些选项:
参考JSON#parse
,返回查看JSON#load
的源代码,倒数第三行是result = parse(source, opts)
,所以load
实际上是{{1 }}和四个默认选项。
这是原因:
parse
另一种方法,如果要解析的对象响应JSON.load("123") #=> 123
JSON.parse("123", quirks_mode: true) #=> 123
的含义是文件,则to_io
仍然有意义。但是,解析则不行。