无法让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
相关产品推荐
相关产品推荐

