2016-12-16 49 views
1

我已經構建了一個接收JSON的Rails API。我想驗證請求主體是否是有效的JSON,如果不是,則在API響應中提供有效的錯誤。花了很多時間嘗試不同的選擇,試圖找到答案,但沒有成功。Rails:在API控制器方法之前驗證JSON請求格式

無論我做什麼來嘗試捕獲錯誤,當我發送一些不正確的測試JSON時,它總是會拋出以下錯誤。

JSON::ParserError at /api/v1/apikey123 

743: unexpected token at '{ 
    "query": "hi there" (missing comma here on purpose) 
    "lang": "en", 
    "sessionId": "en" } 

json (2.0.2) lib/json/common.rb, line 156 

``` ruby 
151  # additions even if a matching class and create_id was found. This option 
152  # defaults to false. 
153  # * *object_class*: Defaults to Hash 
154  # * *array_class*: Defaults to Array 
155  def parse(source, opts = {}) 
> 156  Parser.new(source, opts).parse 
157  end 
158 
159  # Parse the JSON document _source_ into a Ruby data structure and return it. 
160  # The bang version of the parse method defaults to the more dangerous values 
161  # for the _opts_ hash, so be sure only to parse trusted _source_ documents. 

這裏是我的代碼:

module Api 
    class ApiController < ApplicationController 
    protect_from_forgery with: :null_session 
    before_action :authenticate, :parse_request 

    private 
    def parse_request 
     begin 
     @user_input = JSON.parse(request.body.read) 
     rescue JSON::ParserError => e 
     return false 
     end 
    end 

    ... 

    end 
end 

我想知道如何處理這不拋出一個錯誤,發回了一個錯誤消息的響應「無效的JSON格式」

+0

我剛剛發現,如果我從請求標題中刪除Content-Type:application/json,它就完美了!看起來這是從其他地方調用的...這是正常的Rails行爲嗎? – pronoob

回答

1

您應該在救援區塊中調用render方法。由於您致電render,操作方法將會暫停。

def parse_request 
    begin 
    @user_input = JSON.parse(request.body.read) 
    rescue JSON::ParserError => e 
    render json: {error: "Invalid JSON format"}, status: :unprocessable_entity 
    end 
end 
+0

好主意!然而,在到達救援線路之前,我仍然遇到了上述錯誤:-( – pronoob

+0

我剛剛發現,如果我從請求頭中刪除Content-Type:application/json,它完美地起作用!!看起來這個從其他地方調用...這是正常的Rails行爲嗎? – pronoob

+2

如果您發送帶有json內容類型的請求,那麼Rails中間件會在解析它之前將其傳遞到控制器中,因此,當您移除內容類型時,Rails將不會解析正文json。你應該閱讀這篇文章關於捕捉json錯誤https://robots.thoughtbot.com/catching-json-parse-errors-with-custom-middleware –