在使用 `compojure.api` 生成Swagger文档时遇到的问题
我正在使用 compojure.api.sweet 来实现REST端点:
(defroutes http-routes
(context "/payrolls" []
:tags ["Payrolls"]
(POST "/" [company-id]
:body [doc Payroll]
(ability/authorize! :create :payrolls {:company-id company-id})
(json-response (ds/insert! core/payrolls doc)))))
这没问题,当我调用Swagger的 URL时,我得到了期望的API文档输出:

Payroll 是通过 schema.core/defschema 定义的。如果把 :body 改为同时接受一个map或一个map数组:
:body [doc (cond-pre Payroll [Payroll])]
那么对象在文档输出中就消失了:

有没有简单的方法让 schema.core/cond-pre 函数能与Swagger文档配合工作?
解决方案
我最终用 (cond-pre Payroll [Payroll]) 代替了:
(OptArray Payroll)
如果 Payroll 有一些自定义类型,例如:
{:payroll-id ObjectId}
那么我们需要为该类型以及Swagger转换都定义一个:
(ns <namespace>
(:require
[ring.swagger.json-schema :refer [JsonSchema]]
[schema.core :refer [Schema]]
[schema.spec.core :refer [CoreSpec]]
[schema.utils :refer [->ErrorContainer]])
(:import [org.bson.types ObjectId]))
(defrecord ObjectIdCoreSpec []
CoreSpec
(subschemas [_]
[])
(checker [_ _]
#(try
(ObjectId. %)
(catch Exception _e
(->ErrorContainer %)))))
(def ObjectIdSpec (->ObjectIdCoreSpec))
(defrecord ObjectIdSchema []
Schema
(spec [_]
(->ObjectIdSpec))
(explain [_]
'ObjectId))
(def ObjectId (->ObjectIdSchema))
(extend-protocol JsonSchema
ObjectIdSchema
(convert [_ _]
{:type "string"
:format "ObjectId"
:example (str (ObjectId.))}))
OptArray 被定义为:
(ns <namespace>
(:require
[ring.swagger.json-schema :refer [->swagger JsonSchema]]
[schema.coerce :refer [coercer json-coercion-matcher]]
[schema.core :refer [cond-pre Schema]]
[schema.spec.core :refer [CoreSpec]]))
(defrecord OptArrayCoreSpec [schema]
CoreSpec
(subschemas [_]
[])
(checker [_ _]
(let [check (coercer (cond-pre schema [schema])
json-coercion-matcher)]
#(check %))))
(defrecord OptArraySchema [schema]
Schema
(spec [_]
(->OptArrayCoreSpec schema))
(explain [_]
'OptArray))
(defn OptArray [schema]
(->OptArraySchema schema))
(extend-protocol JsonSchema
OptArraySchema
(convert [{:keys [schema]} opt]
(->swagger schema opt)))
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。