新手问题 Grape 的 JSON 参数验证,以及 nested params 问题

seaify · 2015年08月30日 · 最后由 gwq 回复于 2017年12月28日 · 5449 次阅读

两个问题

  1. grape,看文档并不支持对 json parameters, 进行 require 等操作? 它的 require 一个参数后,实际上对应生成的 swagger-ui,都是 form 表单,而且通过 postman,也只有以 form 形式提交的请求才正常
  2. grape, 对于 nested params, 似乎一直报错?
params do
  requires :id, type: Integer, desc: "播放器id"
  requires :name, type: Hash do
    requires :first_name
    requires :last_name
  end
end

而另一种写法

params do
       requires :id, type: Integer, desc: "播放器id"
       requires "name[first]", type: Integer, desc: "空闲内存"
       requires "name[last]", type: Integer, desc: "空闲内存"
     end

grape 使用好像没有发现类似的问题。你先在 log 中,看看 post 后,grape 解析后的参数。

http request header 中设置 content-type 为 application/json,传 json 参数是没有问题的

#2 楼 @alucardpj

传递 json 参数确实没问题,我说的问题是,比如这个 json {"name": "chuck"},我需要确认 json 中这个 name 字段要有,如果使用 requires :name, 没有作用,

传 json 参数要设置 Content-Type header 为 application/json, grape 会调用自带的 Grape::Parser::Json 去解析。

可参考 API Data Formats 文档:https://github.com/ruby-grape/grape#api-data-formats

我比较奇怪

requires :name, type: Hash do
  requires :first_name
  requires :last_name
end

为什么还会出现 name filed,按道理应该只会出现name[first_name], name[last_name]?

#5 楼 @justin

这个我也奇怪,因为 name 出现,根本就不是我想要的,peatio 的 api 文档也是这样的,https://yunbi.com/documents/api_v2#!/orders/POST_version_orders_multi_format

正是因为这个奇怪的问题,我才改成下面那样去绕

requires "name[first]", type: Integer, desc: "空闲内存"
requires "name[last]", type: Integer, desc: "空闲内存"

#4 楼 @jan

感谢你的回复,明白了该怎么去自定义数据 format。

我更关心的是 json 的这种数据格式,能否通过 params, requires, desc 这些关键字来对参数验证,以及 swagger-ui 能否合理的根据这些 api 信息合理的生成相应的页面,用来方便的模拟请求。

#6 楼 @seaify

grape (0.11.0)
grape-swagger (0.10.1)
grape-swagger-rails (0.1.0)

我这边这个版本是不会有问题的 而且我看到 peatio 的 api 里面 orders 的 Data Type 是 Array

不知道 grape swagger rails 有没有暴露出定义的选项,swagger ui 是支持 body 参数使用 JSON 的,但是发的时候需要自己把整个 JSON 复制进去(有 JSON scehma 验证,也可以一键填充默认的 JSON) 没有表单的提交方式,长得像这样

#10 楼 @doitian

非常感谢,这正是我想要看的。grape-swagger 的文档里看到有这个,param_type: 'body',还没试。

你的这个效果图,是 swagger-ui 结合什么弄出来的?

另外看这个图,grape 应该是没有办法支持指定 body 这个 json 里,必须包含 name 字段,这种限制条件吧?

#9 楼 @hammer

感谢回复。

我也有用了 ActionController::Parameters,只是你的这段代码,看样子,是处理 form 表单,且字段名是 project[xxx],可我想要的是 json。

#8 楼 @justin

嗯。版本问题,我这边版本低了,和 peatio 一样。不过 Data Type 是 Array,即便是 array, 我的理解里,也不应该有 name 这个字段。

#8 楼 @justin

囧。升级后,直接不可用了。

ActionController::RoutingError (No route matches [GET] "/api/v1/swagger_doc/screens.json"):

路由找不到了。估计 add_swagger_documentation,生成的那个 url,其包含的 json 信息不对了。

mount API => '/'
mount GrapeSwaggerRails::Engine => '/api/docs'

这是我 router 的配置

#15 楼 @justin

我没有用 grape-swagger-rails,是直接把 swagger-ui 的那些 js, css 文件拷贝到 asset, 而那些路由是 ruby-china,和 peatio 两边都参考了下。

我也试下 grape-swagger-rails

请问你的问题解决了没有?我也遇到同样问题。

#17 楼 @lelewan

我不知道你说的是什么问题。

我现在没有使用 param requires 这些,使用的 gem 的版本

gem 'grape', '~> 0.7.0'
gem 'grape-entity', '~> 0.4.2'
gem 'grape-swagger', '~> 0.7.2'

gem 升级后的问题没有解决,还没有尝试 grape-swagger-rails,直接在做另一个项目了。

@seaify 我用 curl 请求 hash 格式通不过 requires 校验,后来改用 rest_client 就可以了,应该是我 curl 格式搞错了,谢谢回复。

#19 楼 @lelewan

能不能贴上你的 grape 函数,只需要包含 require 部分,以及你使用的 rest_client post 过来的时候 content-type 是 json 吗?

@seaify

desc "增加资源"
params do
  requires :field, type: Hash, allow_blank: false do
    requires : field1, type: String, allow_blank: false
    requires : field2, type: String, allow_blank: false
  end
end
post do
  result = REDIS.hgetall:"#{params[:field][:field1]}"
  if result.blank? 
      REDIS.hset:"#{params[:field][:field1]}",FIELD2,"#{params[:field][:field2]}"  
  else
    {:error => "#{params[:field][:field1]}已经存在" }
  end
end

rest-client 安装后执行 restclient。终端请求格式:

RestClient.post "http://localhost:9000/api/v1/demo", { 'field' => {'field1' => 'X12345','field2' => 'iii'} }.to_json, :content_type => :json, :accept => :json

#10 楼 @doitian 请教一下这个图 grape 是怎么写的?

params do
  requires :body
end

这样的 json 会多出来一层。

seaify 回复

我也遇到这种问题了,请问该怎么解决

需要 登录 后方可回复, 如果你还没有账号请 注册新账号