You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法让compojure-api正确验证带Inst schema的查询参数错误数据

刚搞定了用metosin/compojure-api搭建GET /fetch端点,结合plumatic/schema做查询参数校验,还借助siilisolutions/humanize把生硬的Schema错误信息改成更人性化的提示,分享下我的实现方案:

1. 先搞定依赖

首先确保你的项目里引入了这三个库,我用的是deps.edn,配置如下:

{:deps {metosin/compojure-api {:mvn/version "2.0.0-alpha3"}
        plumatic/schema {:mvn/version "1.1.12"}
        siilisolutions/humanize {:mvn/version "0.1.0"}}}

如果是Leiningen的话,把对应依赖加到project.clj的:dependencies里就行。

2. 定义查询参数的Schema

先给/fetch端点的查询参数定义校验规则,比如我需要日期类型的起始时间、正整数页码、1-100的每页条数:

(require '[schema.core :as s])

;; 定义查询参数的Schema,包含自定义约束和提示
(def FetchQueryParams
  {:start-date java.util.Date
   :page (s/constrained s/Int pos-int? "页码必须大于0")
   :limit (s/constrained s/Int #(<= 1 % 100) "每页条数必须在1-100之间")})
3. 实现人性化的异常处理函数

这一步是核心,把Schema抛出的校验异常转换成用户能看懂的友好提示。我补全了你给出的部分代码,加上了日期类型错误的匹配规则:

(require '[schema.utils :as su]
         '[siilisolutions.humanize :as humanize]
         '[clojure.core.match :as match]
         '[clojure.string :as str])

(defn humanize-schema-exception [^Exception e]
  (if (instance? su/ErrorContainer (ex-data e))
    (let [error (:error (ex-data e))]
      ;; 用humanize解析错误,自定义匹配特定类型的错误提示
      (->> (humanize/explain error
                             (fn [x]
                               (match/match x
                                 ['not ['instance? java.util.Date _]] "必须是有效的日期格式"
                                 ;; 其他类型的错误用默认的人性化提示
                                 :else (humanize/default-humanizer x))))
           ;; 把每个错误信息首字母大写,再用逗号拼接
           (map #(str/capitalize %))
           (str/join ", ")))
    ;; 如果不是Schema校验异常,直接返回原异常信息
    (ex-message e)))
4. 配置Compojure-API端点

最后把这些整合到API路由里,指定用我们的异常处理器来处理Schema校验错误:

(require '[compojure.api.sweet :refer :all]
         '[ring.util.http-response :refer :all])

(def app
  (api
    ;; 配置异常处理器,指定Schema错误用我们的人性化函数处理
    {:exceptions {:handlers {:schema humanize-schema-exception}}}
    (context "/api" []
      (GET "/fetch" []
        ;; 绑定并校验查询参数到变量q
        :query-params [q :- FetchQueryParams]
        :summary "根据查询参数获取数据"
        ;; 模拟返回数据,实际业务逻辑替换这里就行
        (ok {:data "模拟返回的业务数据" :received-params q})))))
效果示例

比如用户传入无效参数:/api/fetch?start-date=invalid-date&page=0&limit=200,原本生硬的Schema错误会被转换成:

必须是有效的日期格式, 页码必须大于0, 每页条数必须在1-100之间

这样用户一眼就能看懂哪里错了~

内容的提问来源于stack exchange,提问作者Freid001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:44:14