json 送信時、空配列が nil になっちゃう

json で、 { entries: [] } のようなパラメータを送ったところ、リクエストを受けた後の params は { entries: nil } となってました。

空配列は nil になっちゃうの?と思ったけど、まっさらなプロジェクトで挙動を確認してみる。

環境

準備

適当にプロジェクト作る

bundle exec rails new . -BJTS
bundle exec rails g resource entries
bundle exec rails s -b 192.168.56.101
bundle exec rake db:migrate

あと application_controller.rb の protect_from_forgery を :null_session に変更しました。

確認

作ったプロジェクトに、json を適当に投げて確認してみる

まずは普通のjsonCurl で。

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" \
  -X POST -d '{"entry": {"name": "hoge"}}'  http://192.168.56.101:3000/entries

ログ

Processing by EntriesController#create as JSON
  Parameters: {"entry"=>{"name"=>"hoge"}}

大丈夫そう(MissingTemplateはスルー)

本題の空配列をなげてみる

$ curl -v -H "Accept: application/json" -H "Content-type: application/json" \
  -X POST -d '{"entry": {"name": []} }'  http://192.168.56.101:3000/entries

ログ

Processing by EntriesController#create as JSON
  Parameters: {"entry"=>{"name"=>nil}}

あ、やっぱり []nil になってますね

ログにこんなメッセージもでてる。

Value for params[:entry][:name] was set to nil, because it was one of [], [null] or [null, null, ...]. 
Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation for more information.

Ruby on Rails Security Guide — Ruby on Rails Guides を見るとセキュリティ対策の模様。 rails 4.1 から導入されたらしい

これをオフにするにはコンフィグを設定します。

config.action_dispatch.perform_deep_munge = false

コンフィグ設定後、同じJSONを送ったところ、今度はちゃんと空の配列が受け取れました。

Processing by EntriesController#create as JSON
  Parameters: {"entry"=>{"name"=>[]}}

しかし

guides.rubyonrails.org のさっきのページに、jsonrails が置き換えた後の params の対応表が書いてあり、以下になっている

JSON               Parameters
{ "person": [] }   { :person => [] }

でも、実際に試すと、

{ "person": [] }   { :person => nil }

こうなっちゃう。 そもそも、ただオフにするのでは、セキュリティ的に問題がありそうだしなぁ


調べる

それっぽいIssueたち

{ entries: [] } で空配列のまま受け取れるのは、rails 5 からなのかな? 4系には入ってなさそ

明日以降、もうちょい Issue を頑張って読みます...><