在Grape中支持多种JSON内容类型

时间:2015-01-14 16:58:35

标签: ruby json api grape

我一直在使用Grape编写类似Evernote的API,并且一直使用Collection + JSON(MIME类型" application / vnd.collection + json")。我现在也想支持JSON API(mime类型" application / vnd.api + json")。

(我之所以这样做是因为编写Ember客户端会更容易,因为Ember Data支持内置的JSON API。编写客户端JavaScript来解决我的问题可能更有意义,但我在Ruby方面比JavaScript更强大。)

我的目标是让服务器支持任一格式,并根据Accept标头选择哪一种格式。这是一个合理的事情,或者拥有多个JSON类型没有意义吗?似乎Grape不支持这一点。如果我只是错误的想法,那么下面的代码可能与该答案无关。

以下是我的服务器代码的一些相关部分:

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。

这个想法是在两种情况下使用相同的Representer,但是根据Accept标头调用适当的方法。

当我使用任何Accept标头对此运行curl时,响应具有Content-Type:application / json,并且在representer上调用“to_json”。如果我遗漏content_type :json, ‘application/json’行,我每次都会收到406 Not Acceptable响应。

我发现在Grape库中,在lib / grape / middleware / formatter.rb中,&#34;格式&#34;对于任何这些MIME类型,请求被视为JSON,因为vnd.collection +或vnd.api +部分是从标头中解析出来的。所以我的问题是,这是葡萄不支持我想要做的事情,还是我想做一些毫无意义的事情?

1 个答案:

答案 0 :(得分:0)

我找到了一个合理的方法来做到这一点,我觉得我很满意,但我认为这完全不符合Grape希望你做的事情。

我创建了一个名为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

所以现在要在presenter对象上调用to_json_api或to_collection_api(或to_json),具体取决于Accept标头。我还没有解决的一个问题是在所有情况下Content-Type都设置为application / json。