39

我正在编写一个 API,它接收一个 JSON 有效负载作为请求正文。

为了目前得到它,我正在做这样的事情:

post '/doSomething' do
    request.body.rewind
    request_payload = JSON.parse request.body.read

    #do something with request_payload
    body request_payload['someKey']
end

有什么好方法可以把它抽象出来,这样我就不需要为每条路线都做这件事了?我的一些路线比这更复杂,因此 request.body 将使用这种方法在每条路线上重新读取和重新解析多次,我想避免这种情况。

有没有办法让 request_payload 神奇地用于路由?像这样:

post '/doSomething' do
    #do something with request_payload, it's already parsed and available
    body request_payload['someKey']
end
4

5 回答 5

65

在处理程序之前使用 sinatra:

before do
  request.body.rewind
  @request_payload = JSON.parse request.body.read
end

这会将其公开给当前的请求处理程序。如果您希望它向所有处理程序公开,请将其放在超类中并在处理程序中扩展该类。

于 2013-06-11T16:57:04.013 回答
9

你也可以使用 Rack Middleware 来解析它。请参阅https://github.com/rack/rack-contribuse Rack::PostBodyContentTypeParser在初始化您的 Sinatra 类时。

于 2016-01-11T20:45:54.590 回答
6

像这样适用于 sinatra 1.4.5

before do
  if request.body.size > 0
    request.body.rewind
    @params = ActiveSupport::JSON.decode(request.body.read)
  end
end
于 2014-09-05T05:12:45.803 回答
2
before do
  request.body.rewind
  @request_payload = JSON.parse(request.body.read, symbolize_names: true)
end

因此,您还可以在解析 JSON 请求正文时使用 symbolize_names,这将使您能够像这样访问嵌套参数@request_payload[:user]

于 2019-09-06T09:12:46.727 回答
2

您可以从https://github.com/rack/rack-contribHash解析您的JSON 帖子正文:Rack::PostBodyContentTypeParser

require 'rack/contrib/post_body_content_type_parser'

class Api < Sinatra::Application
  use Rack::PostBodyContentTypeParser
  ...
end

您甚至可以传递一个自定义块来Rack::PostBodyContentTypeParser将 JSON 解析为符号而不是字符串:

a_proc = proc { |body| JSON.parse(body, symbolize_names: true, create_additions: false) }
use Rack::PostBodyContentTypeParser, &a_proc
于 2020-03-14T00:28:33.030 回答