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

Wen*_*Wen 32 ruby json

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

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

parse(source,opts = {}) 将JSON文档源解析为Ruby数据结构并返回它.

Kas*_*yap 30

JSON#parse 将JSON字符串解析为Ruby Hash.

 JSON.parse('{"name": "Some Name"}') # => {"name" => "Some Name"}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

实际上,它会转换响应#read方法的任何对象.例如:

class A
  def initialize
    @a = '{"name": "Some Name"}'
  end

  def read
    @a
  end
end

JSON.load(A.new)                      # => {"name" => "Some Name"}
Run Code Online (Sandbox Code Playgroud)


Fre*_*ung 20

一个关键的区别是,JSON.load当给出不受信任的输入时是不安全的(同样可以实现JSON.parse,但它有安全的默认值).这是因为它提供了一种实例化"普通"Hash,String,Array,Number类以外的类的方法:

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"} 
Run Code Online (Sandbox Code Playgroud)

JSON.load('{"json_class": "Foo"}')
called with {"json_class"=>"Foo"}
#=> nil
Run Code Online (Sandbox Code Playgroud)

这旨在让您实现数据的自定义序列化 - 在解析来自广阔世界的数据时不应使用它.当然,您确实需要实现json_creatable?json_create方法来实际实现任何目标,但是您有多大的信心,没有任何依赖关系这样做或method_missing以可能被误用的方式实现?(参见例如Marshal.load攻击.作为这样的结果JSON.loadJSON.parse被显著收紧).

始终JSON.parse在处理不受信任的数据时使用,或者除非您需要额外的功能JSON.load


Fle*_*oid 19

另一个区别是JSON.load默认情况下解析单个值(不是对象而不是数组).

JSON.load("false")
=> false

JSON.load("123")
=> 123
Run Code Online (Sandbox Code Playgroud)

JSON.parse需要quirks mode启用解析此值.

JSON.parse("false")
JSON::ParserError: 757: unexpected token at 'false'

JSON.parse("false", quirks_mode: true)
=> false
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你对`quirks_mode`的解释 (3认同)
  • 这不再是事实。在 Ruby 2.4.1 中`JSON.parse("false")` 工作得很好;我猜 `quirks_mode: true` 成为默认值。 (2认同)