Ruby lib的JSON.load和JSON.parse方法有什么区别?

时间:2013-06-21 01:32:11

标签: ruby json

从ruby文档中我可以看到load方法将proc作为arg而parse没有。还有其他区别吗?比方说,当我有一个JSON字符串时,我应该使用哪种方法将其转换为Ruby对象?

  

加载(来源,proc = nil,options = {})   从JSON源加载ruby数据结构并返回它。源可以是类似于字符串的对象,类似IO的对象,也可以是响应read方法的对象。如果给出了proc,它将以任何嵌套的Ruby对象作为参数以深度优先顺序递归调用。要修改默认选项,也要传递可选选项参数。   此方法是Marshal和YAML的加载/转储接口实现的一部分。   别名为:restore

     

解析(来源,操作= {})   将JSON文档源解析为Ruby数据结构并将其返回。

5 个答案:

答案 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中获取一些选项:

  • max_nesting:已解析的数据结构中允许的最大嵌套深度。使用:max_nesting => false禁用深度检查。默认为100。/
  • allow_nan:如果设置为true,则允许解析器解析违反RFC 7159的NaN,Infinity和-Infinity。此选项默认为false。
  • symbolize_names:如果设置为true,则返回JSON对象中名称(键)的符号。否则,返回字符串。字符串是默认值。
  • create_additions:如果设置为false,则即使找到匹配的类和create_id,解析器也不会创建添加项。此选项默认为false。
  • object_class:默认为哈希
  • array_class:默认为Array

为什么

参考JSON#parse,返回查看JSON#load的源代码,倒数第三行是result = parse(source, opts),所以load实际上是{{1 }}和四个默认选项。

这是原因:

parse

另一种方法,如果要解析的对象响应JSON.load("123") #=> 123 JSON.parse("123", quirks_mode: true) #=> 123 的含义是文件,则to_io仍然有意义。但是,解析则不行。