2015-01-14 64 views
0

我一直在使用Grape編寫類似印象筆記的API,並且一直使用Collection + JSON(MIME類型「application/vnd.collection + json」)。我現在想要支持JSON API(mime類型「application/vnd.api + json」)。在Grape中支持多種JSON內容類型

(我想這樣做的原因是編寫Ember客戶端會更容易,因爲Ember Data支持內置的JSON API。編寫客戶端JavaScript來解決我的問題可能更有意義,但我比Ruby更強大)

我的目標是讓服務器支持任一格式,並根據Accept標頭選擇哪一個。這是一件合理的事情嗎?或者它有多種JSON類型沒有意義?看來,葡萄不支持這一點。如果我只是有錯誤的想法,那麼下面的代碼可能與該答案無關。

這裏是我的服務器代碼的一些相關作品:

class NotesServer < Grape::API 
    content_type :json, ‘application/json’ 


    content_type :json_api, 'application/vnd.api+json' 
    formatter :json_api, lambda { |object, env| object.to_json_api } 

    content_type :collection_json, 'application/vnd.collection+json' 
    formatter :collection_json, lambda { |object, env| object.to_collection_json } 

    resource :notes do 
    desc 'Get a note.' 

    params do 
     requires :id, type: Integer, desc: 'Note ID.' 
    end 

    route_param :id do 
     get do 
     NoteRepresenter.new Note.find(params[:id]) 
     end 
    end 
end 

...其中NoteRepresenter定義了to_json_api和to_collection_json。

這個想法是在任何一種情況下使用相同的Delegister,但根據Accept標頭調用適當的方法。

當我用任何Accept頭對此curl運行時,響應具有Content-Type:application/json,並且在代表程序上調用「to_json」。如果我忽略content_type :json, ‘application/json’一行,每次都會收到406不可接受的響應。

我發現在Grape庫中的lib/grape/middleware/formatter.rb中,請求的「格式」被認爲是任何這些MIME類型的JSON,因爲vnd.collection +或vnd.api +部分解析出標題。所以我的問題是,這是一個葡萄不支持我想要做的事情,還是我想做一些沒有意義的事情?

+0

爲什麼'application/vnd.api + json'類型與'application/json'? – tadman

+0

我根本不瞭解Grape,但支持基於Accept頭的多種內容類型*絕對是* HTTP /標準方式來做到這一點,以及合理的方法/目標。 – Pete

+0

@tadman我試圖使用這裏記錄的標準:http://jsonapi.org/,同樣對於收集+ JSON在這裏:http://amundsen.com/media-types/collection/ – Kirkland

回答

0

我發現了一個合理的方法來做到這一點,我很滿意,但我不認爲它完全符合葡萄期望你做的事情。

我創建了一個名爲JsonFormatter自定義格式,所以我的服務器代碼如下所示:

class NotesServer < Grape::API 
    formatter :json, JsonFormatter 
    # … 
end 

而且該格式本身:

module JsonFormatter 
    def self.call(object, env) 
    case env['HTTP_ACCEPT'] 
    when 'application/vnd.api+json' 
     object.to_json_api 
    when 'application/vnd.collection+json' 
     object.to_collection_json 
    else 
     object.to_json 
    end 
    end 
end 

所以現在要麼to_json_api或to_collection_api(或to_json)將在主持人對象上調用,具體取決於Accept頭。我還沒有解決的一個問題是Content-Type在所有情況下都設置爲application/json。

相關問題