Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure.spec keys: separating key name from the spec validating it

Tags:

clojure

I need to validate the shape of clojure maps that have been converted from json strings. The json strings are messages of a protocol I'm implementing. For this I'm trying out clojure.spec.alpha.

I'm using s/keys. Multiple messages in my protocol have the same key names, but differently shaped values attached to those keys, so they cannot be validated by the same spec.

An example:

;; 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]))

I think I could define the :status spec in different namespaces, but it seems overkill to me. After all it's just different messages in the same protocol and i just have a couple of clashes.

Is there a way for (s/keys) to separate the name of the key whose presence is being checked from the name of the spec that is validating it?

like image 624
white-surf-style-five Avatar asked May 09 '17 07:05

white-surf-style-five


1 Answers

In spec, qualified keywords are used to create global semantics (via the spec) whose name is the qualified keyword. If you use the same qualified keyword with different semantics, I'd say you should change your code to use different qualifiers :ex1/status and :ex2/status for different semantics.

If you are using unqualified keywords (not uncommon when coming from JSON), you can use s/keys and :req-un to map different specs to the same unqualified keyword in different parts of your data.

(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
like image 73
Alex Miller Avatar answered Oct 09 '22 03:10

Alex Miller