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

如何为Datomic返回的带命名空间关键字的数据编写Clojure Spec?

问题根源与解决方案

核心问题

你遇到的问题来自两个关键误解:

  1. 混淆了关键字命名空间与代码命名空间:schema.event是你的Clojure代码命名空间,但你定义的Spec是针对关键字:event/date(命名空间为event),两者没有绑定关系——关键字的命名空间是其自身属性,和代码所在的命名空间无关。
  2. 错误使用了:req-un选项:s/keys的:req-un参数用于要求Map中存在不带命名空间的关键字,并将其关联到带命名空间的Spec;而你需要验证的是Datomic返回的带命名空间的:event/date,因此:req-un完全不匹配你的需求。

正确的Spec写法

1. 保持schema.event的定义不变

(ns schema.event
  (:require [clojure.spec.alpha :as s]))

; 定义针对关键字:event/date的全局Spec
(s/def :event/date string?)

2. 在主命名空间编写验证Spec

(ns your.app.namespace
  (:require [clojure.spec.alpha :as s]
            [schema.event])) ; 引入schema.event,让其中的Spec定义生效

; 定义::id的Spec
(s/def ::id string?)

; 使用:req参数指定必须存在的带命名空间关键字
(s/def ::result
  (s/keys :req [::id :event/date]))

验证测试

; 验证Datomic返回的带命名空间的Map
(s/valid? ::result {:id "123abc" :event/date "1/1/2020"}) ; => true

; 验证不带命名空间的Map(会失败,符合预期)
(s/valid? ::result {:id "123abc" :date "1/1/2020"}) ; => false

额外说明

如果需要用别名关联关键字(比如想在Spec里用::event-date对应:event/date),可以用s/keys的:req配合别名定义:

(ns your.app.namespace
  (:require [clojure.spec.alpha :as s]
            [schema.event]))

(s/def ::id string?)
(s/def ::event-date :event/date) ; 给:event/date的Spec起别名

(s/def ::result
  (s/keys :req [::id ::event-date])) ; 使用别名验证

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:31:06