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

Clojure.spec中类似s/and的or操作:验证两种Web响应结构

简洁处理二选一的响应结构验证

嘿,我太懂你这种不想杀鸡用牛刀的心情了!对于你这种两种简单映射结构的场景,完全没必要动用multi-spec——clojure.spec.alpha/s/or就是最适配的轻量工具,它专门用来定义多个可选的有效结构,语法简洁到恰到好处。

咱们直接上实操代码:

首先分别定义两种响应的独立spec:

(require '[clojure.spec.alpha :as s])

;; 第一种响应:包含assignment字段的映射
(s/def ::assignment string?)
(s/def ::assignment-response (s/keys :req-un [::assignment]))

;; 第二种响应:包含no-more-assignments字段的映射
(s/def ::no-more-assignments boolean?)
(s/def ::no-more-response (s/keys :req-un [::no-more-assignments]))

然后用s/or把它们组合成一个统一的响应spec,给每个分支起个短名字,后续验证失败时能快速定位问题:

(s/def ::server-response
  (s/or :has-assignment ::assignment-response
        :no-more ::no-more-response))

现在来验证下效果:

;; 验证合法的第一种响应
(s/valid? ::server-response {:assignment "1232123"}) ; => true

;; 验证合法的第二种响应
(s/valid? ::server-response {:no-more-assignments true}) ; => true

;; 验证无效的响应(不符合任何一种结构)
(s/valid? ::server-response {:random-key "oops"}) ; => false

如果需要看详细的失败原因,用s/explain-str就能拿到清晰的报错信息:

(s/explain-str ::server-response {:random-key "oops"})
;; 输出示例:
;; "Spec failed: In: [] val: {:random-key \"oops\"} fails at: [:has-assignment] predicate: (contains? % :assignment), fails at: [:no-more] predicate: (contains? % :no-more-assignments)
;;  :clojure.spec.alpha/spec #object[clojure.spec.alpha$regex_spec_impl$reify__2509 0x...], :clojure.spec.alpha/value {:random-key \"oops\"}, :clojure.spec.alpha/failure :multi-spec"

这个方案的优势很明显:

  • 代码极简,完全贴合你这种简单二选一的场景
  • 报错信息直观,能一眼看出是哪个分支的验证没通过
  • 不需要额外写dispatch函数,比multi-spec轻量太多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:38:44