使用compojure.api生成Swagger文档时的cond-pre兼容问题
解决schema.core/cond-pre与Compojure API Swagger兼容的问题
核心原因是Compojure API的Swagger生成器默认无法自动解析cond-pre这类条件型Schema,需要手动补充Swagger元数据或改用更兼容的Schema定义方式,以下是几个简便方案:
方法1:给cond-pre添加Swagger元数据
直接在cond-pre定义中通过元数据指定Swagger可识别的oneOf类型,明确告知其支持单个对象或数组:
(schema.core/defschema Payroll {:id schema/Int :amount schema/Num}) (def PayrollOrArray ^{:swagger {:oneOf [(schema.core/resolve-schema Payroll) (schema.core/resolve-schema [Payroll])]}} (schema.core/cond-pre Payroll [Payroll]))
之后在接口中使用PayrollOrArray作为请求体Schema,Swagger即可正常渲染对应的结构。
方法2:用schema.core/either替代cond-pre
either本身表示"多个类型任选其一",Compojure API的Swagger生成器对其原生支持更好,无需额外配置就能自动生成正确的文档:
(schema.core/defschema Payroll {:id schema/Int :amount schema/Num}) (def PayrollOrArray (schema.core/either Payroll [Payroll]))
这种方式下Swagger会自动识别为oneOf类型,展示单个Payroll对象和Payroll数组两种可选结构。
方法3:在接口中手动指定Swagger请求体结构
如果前两种方案不适用,可直接在接口的:swagger配置里强制定义请求体的Schema结构:
(POST "/payroll" [] :body [payload PayrollOrArray] :swagger {:requestBody {:content {"application/json" {:schema {:oneOf [(schema.core/resolve-schema Payroll) (schema.core/resolve-schema [Payroll])]}}}}} :return schema/Boolean (ok true))
通过这种方式直接告诉Swagger请求体的结构,也能让文档正常显示。
注意:cond-pre在运行时是按顺序匹配第一个符合的Schema,而Swagger的oneOf不区分顺序,但在单个对象和数组的场景下,这种差异几乎不会影响实际使用。
内容的提问来源于stack exchange,提问作者Lars Melander
相关产品推荐
相关产品推荐

