What's the difference between JSON.load and JSON.parse methods of Ruby lib?

JSON#parse parses a JSON string into a Ruby Hash.

 JSON.parse('{"name": "Some Name"}') # => {"name" => "Some Name"}

JSON#load takes either a string or IO (file etc) and converts that to 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

In fact, it converts any object that responds to a #read method. For example:

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

  def read
    @a
  end
end

JSON.load(A.new)                      # => {"name" => "Some Name"}

A key difference is that JSON.load is unsafe when given untrusted input (the same can be achieved with JSON.parse, but it has safe defaults). This is because it provides a way to instantiate classes other than the "normal" Hash, String, Array, Number classes:

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"} 

whereas

JSON.load('{"json_class": "Foo"}')
called with {"json_class"=>"Foo"}
#=> nil

This intended for you to implement custom serialization of data - it shouldn't be used when parsing data from the wide world. Of course you do need to implement the json_creatable? and json_create methods for this to actually achieve anything, but how confident are you that none of your dependencies do this or implement method_missing in such a way that it could be misused ? (see for example the Marshal.load exploits. As a result of this JSON.load & JSON.parse were tightened up significantly).

Always use JSON.parse when dealing with untrusted data or unless you need the extra capabilities of JSON.load


One more difference is that JSON.load parses single value (not object and not array) by default.

JSON.load("false")
=> false

JSON.load("123")
=> 123

But JSON.parse requires quirks mode to be enabled to parse such value.

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

JSON.parse("false", quirks_mode: true)
=> false

Tags:

Ruby

Json