首页 > 解决方案 > Compojure-api:请求强制通过 multipart-params 提供的地图

问题描述

我正在尝试将 compojure-api(版本 1.1.12)集成到现有的基于 compojure 的应用程序中。虽然大多数事情都有效,但我在现有 REST 调用上的请求强制存在问题,此时其用法很难更改。

我这样定义路线:

(POST "/endpoint" request
    :multipart-params 
        [required-strings :- (describe [s/Str] "Required, an array of strings"),
         {optional-string :- (describe s/Str "An optional string") ""},
         {others :- {s/Keyword s/Any} {}}]
    ...)

这有效,除非我尝试传递other-parameters请求。例如,通过 curl:

curl -F "required-strings=[\"Hello\"]" -F "others={\"a\":1.0}" ...

这会导致内容无效请求(即状态 400)错误:

{"errors":{"others":"(not (map? a-clojure.lang.PersistentVector))"}}

我正在使用 ring-default's site-defaults,并且我没有修改 compojure api 的默认强制。我已将错误追踪到compojure.api.coerce/coerce. 我可以看到强制器正在处理的值,它看起来像:

{:required-strings "[\"Hello\"]"
 :others "{\"a\":1.0}"}

在 coerce.clj 的第 59 行,(coerce value)返回一个错误 (per schema.utils/error?)。

那么,是否不可能将 JSON 编码的多部分参数强制转换为 Clojure 映射?我可以将参数定义为字符串而不是映射,并自己进行解析,但这违背了使用 compojure-api 和 ring-swagger 的目的。

标签: clojurecompojurecompojure-api

解决方案


for 的强制器others需要一个 clojure 映射而不是一个字符串。为了使它工作,你必须选择。

第一个选项:添加wrap-json-params中间件并application/json请求而不是multipart/form-data

curl ... -H 'Content-Type: application/json' \
     -d $'{
  "required-strings": ["Hello"],
  "others": {"a": 1.0}
}'

第二个选项:添加wrap-nested-params中间件并multipart/form-data使用嵌套参数名称请求:

curl ... -H 'Content-Type: multipart/form-data' \
     -F "required-strings[]=Hello" \
     -F "others[a]=1.0" 

推荐阅读