在使用 `compojure.api` 生成Swagger文档时遇到的问题

后端开发 2026-07-09

我正在使用 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文档输出:

正确的 Swagger 文档

Payroll 是通过 schema.core/defschema 定义的。如果把 :body 改为同时接受一个map或一个map数组:

      :body [doc (cond-pre Payroll [Payroll])]

那么对象在文档输出中就消失了:

错误的 Swagger 文档

有没有简单的方法让 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章