

Ruby の JSON モジュールには JSON を読み込むためのメソッドとして load と parse が用意されています。

両者は用途が殆ど同じように見えるのですが、何かしら大事な挙動の違いや使い分けがあるのでしょうか？
「こういうときはこちらを使った方が良い」というのはありますか？ パッと見では load の方が高機能に見えるのですが parse
は何のために用意されたのでしょうか。

  * <https://docs.ruby-lang.org/ja/latest/class/JSON.html#M_LOAD>

> 与えられた JSON 形式の文字列を Ruby オブジェクトとしてロードして返します。

  * <https://docs.ruby-lang.org/ja/latest/class/JSON.html#M_PARSE>

> 与えられた JSON 形式の文字列を Ruby オブジェクトに変換して返します。


CC BY-SA 4.0
2020-05-14T22:40:09.680
66614
2020-05-23T13:08:21.630
19110
question
ruby
JSON.load と JSON.parse の違いは何ですか？


`JSON.load` は内部で `JSON.parse` を利用しています。そして、それぞれは目的が違います。

`JSON.parse` は、JSON文字列に対して、それを ruby
の組み込み型で読み込むことを目的に実装されています。その挙動は、資料に依れば、基本的には [RFC 4627](https://www.rfc-
editor.org/rfc/rfc4627)準拠の読み込み動作を行います。(例: NaN や Infinity は rfc
に規定されていないので、読み込みエラーになる。これを `Float::NaN` などで読み込むためには、 `allow_nan: true` を指定する)

`JSON.load` は、もう少し汎用的なことを目的としていて、「ruby
的なオブジェクトを読み込む」ことができるように設計されています。具体的には、string だけではなく IO オブジェクトを引数にとったり、第2引数で
proc を指定して任意の微調整を行えるようにしたり、 `create_additions` な規約に従い、 Hash ではなく任意の ruby
オブジェクトを読み込みしたり、です。(その実、 `create_additions` は `JSON.parse`
でも可能ですが、しかしデフォルトオプションでは off になっています)

[code]

    class Foo
      def initialize(attrs)
        @attrs = attrs
      end
    
      def self.json_creatable?
        true
      end
    
      def self.json_create(attributes)
        new(attributes.reject { |k| k == 'json_class' })
      end
    end
    
    JSON.load('{"json_class": "Foo", "bar": "piyo", "hoge": "fuga"}')
    # => #<Foo:0x00007fd3811f50c0 @attrs={"bar"=>"piyo", "hoge"=>"fuga"}>
    
[/code]

また、セキュリティ的な観点でも違いがあります。 `JSON.parse` は例えば JSON での api
通信の読み込みにも使いうるように実装されており、そのために、何も考えずに任意の JSON
をパースしても危険じゃないように、もろもろの設定値がデフォルトに設定されています。一方、 `JSON.load`
は主にシリアライズ・デシリアライズが主目的のため、プログラマにとっての利便性が優先されています。(信用できないデータはデシリアライズしては、そもそもいけないよね、という原則論があるような気がします)

具体的に、このように `JSON.parse` と `JSON.load` でデフォルトが異なっているオプションには、
`create_additions`, `allow_nan`, `max_nesting` があります。

* * *

参考: <https://stackoverflow.com/q/17226402/3090068>


CC BY-SA 4.0
2020-05-15T04:01:28.373
66623
2020-05-23T13:08:21.630
2021-10-07T07:34:52.683
-1
754
66614
answer