Clojure.spec键:将键名与验证它的规范分开

whi*_*ive 8 clojure

我需要验证从json字符串转换的clojure贴图的形状.json字符串是我正在实现的协议的消息.为此,我正在尝试clojure.spec.alpha.

我正在使用s /键.我的协议中的多个消息具有相同的密钥名称,但这些密钥附加了不同形状的值,因此无法通过相同的规范进行验证.

一个例子:

;; Here status should have the same key name, but their shape
;; is different. But definining another spec forces me to register it with a
;; different keyword, which breaks the "should have name 'status'" requirement.

(s/def ::a-message 
  (s/keys :req [::status]))

(s/def ::another-message
  (s/keys :req [::status]))
Run Code Online (Sandbox Code Playgroud)

我想我可以在不同的命名空间中定义:status spec,但这对我来说似乎有些过分.毕竟它只是在同一协议中的不同消息,我只是有几个冲突.

(s /键)是否有办法将正在检查其存在的密钥的名称与正在验证它的规范的名称分开?

Ale*_*ler 19

在规范中,限定关键字用于创建全局语义(通过规范),其名称是限定关键字.如果您使用具有不同语义的相同限定关键字,我会说您应该更改您的代码以使用不同的限定符:ex1/status和:ex2/status用于不同的语义.

如果您使用的是非限定关键字(来自JSON时并非罕见),您可以使用s/keys:req-un将不同的规范映射到数据不同部分中的同一个非限定关键字.

(s/def :ex1/status string?)
(s/def :ex2/status int?)

(s/def ::a-message (s/keys :req-un [:ex1/status]))
(s/def ::another-message (s/keys :req-un [:ex2/status]))

(s/valid? ::a-message {:status "abc"}) ;; true
(s/valid? ::another-message {:status 100}) ;; true
Run Code Online (Sandbox Code Playgroud)

  • 我认为在不同的命名空间中拥有规范同时拥有不合格的键是在我的情况下最简单的事情。谢谢! (2认同)