【发布时间】:2015-01-14 16:58:35
【问题描述】:
我一直在使用 Grape 编写类似 Evernote 的 API,并且一直在使用 Collection+JSON(MIME 类型“application/vnd.collection+json”)。我现在还想支持 JSON API(mime 类型“application/vnd.api+json”)。
(我想这样做的原因是因为 Ember Data 支持内置的 JSON API,所以编写 Ember 客户端会更容易。编写客户端 JavaScript 来解决我的问题可能更有意义,但我的 Ruby 比 JavaScript 强。)
我的目标是让服务器支持任何一种格式,并根据 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。
想法是在任何一种情况下都使用相同的 Representer,但要根据 Accept 标头调用适当的方法。
当我使用任何 Accept 标头对此运行 curl 时,响应具有 Content-Type:application/json,并且在表示器上调用了“to_json”。如果我省略了 content_type :json, ‘application/json’ 行,我每次都会收到 406 Not Acceptable 响应。
我发现在 Grape 库中的 lib/grape/middleware/formatter.rb 中,请求的“格式”对于任何这些 MIME 类型都被视为 JSON,因为 vnd.collection+ 或 vnd.api+ 部分从标题中解析出来。所以我的问题是,这是 Grape 不支持我正在尝试做的事情,还是我在尝试做一些没有意义的事情?
【问题讨论】:
-
为什么是
application/vnd.api+json类型与application/json? -
我根本不了解 Grape,但是支持基于 Accept 标头的多种内容类型绝对做到这一点的 HTTP/标准方式,也是一种合理的方法/目标也是如此。
-
@tadman 我正在尝试使用此处记录的标准:jsonapi.org,同样适用于此处的 Collection+JSON:amundsen.com/media-types/collection
-
您可能需要使用 Rack 处理程序将这些映射到常规 JSON,或正确解码它们。