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

时间:2017-05-09 07:17:27

标签: 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]))

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

(s / keys)是否有办法分隔正在检查其存在的密钥的名称 从验证它的规范的名称?

1 个答案:

答案 0 :(得分:18)

在规范中,限定关键字用于创建全局语义(通过规范),其名称是限定关键字。如果您使用具有不同语义的相同限定关键字,我会说您应该更改您的代码以使用不同的限定符: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