我有这个Clojure代码来定义我的回复对象的架构,可以是
{:message {:text "Hello"} :delay 3000}
或
{:action "typing_on" :duration 5000}
reply
地图可以有:message
或:action
以及可选键:delay
和:duration
。
我试图用clojure.spec
:
(s/def ::action #{"typing_on" "typing_off" "mark_seen"})
(s/def ::duration int?)
(s/def ::delay int?)
(s/def ::message map?)
(s/def ::message-reply (s/keys :req-un [::message]
:opt-un [::delay]))
(s/def ::action-reply (s/keys :req-un [::action]
:opt-un [::duration]))
(s/def ::reply (or ::action-reply ::message-reply))
但是,这些规范将使用true
or
在::action-reply
子句中找到的第一个架构进行验证,在本例中为::action-reply
。
我想要实现的目标是::message-reply
或::reply
是{{1}}的有效架构。
答案 0 :(得分:5)
我想你的意思是使用s/or
,而不是or
(在这种情况下这没有用)?
(s/def ::reply (s/or :action-reply ::action-reply
:message-reply ::message-reply))
也许在您的某个值上尝试s/conform
,看看如何使用符合('spec-destructured')值:
(s/conform ::reply {:message {:text "Hello"} :delay 3000})
; => [:message-reply {:message {:text "Hello"}, :delay 3000}]