【Ruby】JSON.loadで変換後、キーをシンボルにしたい!

JSON.loadJSON文字列をRubyのオブジェクトにしたいとき、ちょっぴりつまづいたのでメモ

以下はJSON文字列をloadしてRubyのオブジェクトに変換するコード例

 str=<<JSON
    { "a":1, "b":2, "c":3 }
    JSON
    
    JSON.load(str) # => {"a"=>1, "b"=>2, "c"=>3} # 普通に渡すとキーが文字列になる

↑を:a のようにキーをシンボルにしたい

ということでるりまを見ると、キーをシンボルにするオブションがあった。以下抜粋して引用。

docs.ruby-lang.org

:symbolize_names

真を指定するとハッシュのキーを文字列ではなくシンボルにします。デフォルトは偽です。

お、ということは、:symbolize_namestrueにすれば良い?? やってみた💪🏻

JSON.load(str, symbolize_names: true) # => {"a"=>1, "b"=>2, "c"=>3}  

# おっと変わらないぞ?

あれ、変わらない。

もう一度るりまを見たら

load(source, proc = nil, options = {}) -> object

どうやらprocとoptionsはデフォルト引数になっているらしい。

と、いうことはoptions(今回で言えばsymbolize_names)のデフォルトを書き換えたい場合は、その前の 第二引数でprocについて指定してあげないといけないのかなと思い、やってみる

 JSON.load(str, nil, symbolize_names: true) # 第二引数のproc部分をnilにした

 # => (省略)`initialize': options :symbolize_names and :create_additions cannot be  used in conjunction (ArgumentError) (省略)

なんかエラー出た!!

DeepL先生によると

initialize': オプション :symbolize_names と :create_additions は同時に使用できません (ArgumentError)

らしい。なんのこっちゃ🤔という感じなのでもう一度るりまを見る。

お、それっぽい記述があった!

:create_additions

偽を指定するとマッチするクラスや JSON.create_id が見つかっても付加情報を生成しません。デフォルトは真です。

「「「デフォルトは真。」」」

そして先ほどのエラー文訳、initialize': オプション :symbolize_names と :create_additions は同時に使用できません

ということは、:symbolize_names:create_additionsを今回どちらも真にしてしまったのがよくなかったらしい。

再チャレンジ!

 JSON.load(str, nil, symbolize_names: true, create_additions: false)

 # => {:a=>1, :b=>2, :c=>3} # できた〜!

結論

JSON.loadでキーをシンボルにしたいときは

symbolize_names: trueとともに、

  • 第二引数にprocについてを渡す(今回はnil

  • :create_additions:symbolize_namesと共存できない(どちらもtrueはできない)

  • そのため、create_additions: falseも記述する

ちなみにJSON.parseの場合

docs.ruby-lang.org

parse(source, options = {}) -> objectかつ

:create_additionsがデフォルトでfalse

なので、第二引数にsymbolize_names: trueを記述するだけでキーをシンボルにできる

 JSON.parse('[1,2,{"name":"tanaka","age":19}]', symbolize_names: true)

    # => [1, 2, {:name=>"tanaka", :age=>19}] 

JSON.loadJSON.parseは引数の書き方が違うということがわかった。

&無事キーをシンボルにできたのでヨシ☺️☺️!