【Ruby/Rails】JSONのキーをキャメルケースからスネークケースに、文字列からシンボルに変換する
2021/03/03
問題
APIを叩いて返ってきたレスポンスがJSON形式でキーがキャメルケースの文字列だった
普通にJSON.parseしても問題ないが、Rubyだったらできればスネークケースのシンボルで扱いたい
SwitchBotのAPIレスポンス
devices.json
{
"statusCode": 100,
"body": {
"deviceList": [
{
"deviceId": "500291B269BE",
"deviceName": "Living Room Humidifier",
"deviceType": "Humidifier",
"enableCloudService": true,
"hubDeviceId": "000000000000"
}
],
"infraredRemoteList": [
{
"deviceId": "02-202008110034-13",
"deviceName": "Living Room TV",
"remoteType": "TV",
"hubDeviceId": "FA7310762361"
}
]
},
"message": "success"
}
JSON.parseした結果
JSON.parse(File.open('devices.json').read)
#=> {"statusCode"=>100, "body"=>{"deviceList"=>[{"deviceId"=>"500291B269BE", "deviceName"=>"Living Room Humidifier", "deviceType"=>"Humidifier", "enableCloudService"=>true, "hubDeviceId"=>"000000000000"}], "infraredRemoteList"=>[{"deviceId"=>"02-202008110034-13", "deviceName"=>"Living Room TV", "remoteType"=>"TV", "hubDeviceId"=>"FA7310762361"}]}, "message"=>"success"}
解決方法
deep_transform_keys(&:underscore)
でスネークケースにして、deep_symbolize_keys
でシンボルにする
require 'json'
require 'active_support/all' # Rubyの場合
JSON.parse(File.open('devices.json').read).deep_transform_keys(&:underscore).deep_symbolize_keys
#=> {:status_code=>100, :body=>{:device_list=>[{:device_id=>"500291B269BE", :device_name=>"Living Room Humidifier", :device_type=>"Humidifier", :enable_cloud_service=>true, :hub_device_id=>"000000000000"}], :infrared_remote_list=>[{:device_id=>"02-202008110034-13", :device_name=>"Living Room TV", :remote_type=>"TV", :hub_device_id=>"FA7310762361"}]}, :message=>"success"}
解説的なもの
キーを文字列からシンボルにする方法
方法は2つある
JSON.parseのsymbolize_namesオプション
JSON.parse('{"name": "Takagi"}', symbolize_names: true)
#=> {:name=>"Takagi"}
symbolize_keysメソッド
JSON.parse('{"name": "Takagi"}').symbolize_keys
#=> {:name=>"Takagi"}
※多次元の場合はdeep_symbolize_keys
キーをキャメルケースからスネークケースにする方法
JSON.parse('{"lastName": "Takagi"}').transform_keys(&:underscore)
#=> {"last_name"=>"Takagi"}
※多次元の場合はdeep_transform_keys
symbolize_namesオプションを使わず、symbolize_keysメソッドを使った理由
Symbolクラスにunderscoreメソッドが存在しないため
JSON.parse(File.open('spec/support/fixtures/devices.json').read, symbolize_names: true).deep_transform_keys(&:underscore)
#=> NoMethodError (undefined method `underscore' for :statusCode:Symbol)