Having two following specs:
(s/def ::x keyword?)
(s/def ::y keyword?)
(s/def ::z keyword?)
(s/def ::a
(s/keys :req-un [::x
::y]
:opt-un [::z]))
(s/def ::b
(s/map-of string? string?))
how do I combine ::a
and ::b
into ::m
so the following data is valid:
(s/valid? ::m
{:x :foo
:y :bar
:z :any})
(s/valid? ::m
{:x :foo
:y :bar})
(s/valid? ::m
{:x :foo
:y :bar
:z :baz})
(s/valid? ::m
{:x :foo
:y :bar
:z "baz"})
(s/valid? ::m
{:x :foo
:y :bar
:t "tic"})
additionally, how do I combine ::a
and ::b
into ::m
so the following data is invalid:
(s/valid? ::m
{"r" "foo"
"t" "bar"})
(s/valid? ::m
{:x :foo
"r" "bar"})
(s/valid? ::m
{:x :foo
:y :bar
:r :any})
Neither of :
(s/def ::m (s/merge ::a ::b))
(s/def ::m (s/or :a ::a :b ::b))
works (as expected), but is there a way to match map entries in priority of the spec order?
The way it should work is the following:
- take all the map entries of the value (which is a map)
- partition the map entries into two sets. One confirming the
::a
spec and the other conforming the::b
spec. - The two sub-maps should conform each the relevant spec as a whole. E.g the first partition should have all the required keys.
{"r" "foo" "t" "bar"}
be invalid? It conforms to the::b
spec? – cfrick::b
spec. I want to define a spec which would conform to both::a
AND::b
. E.g::a
a requires:x
and:y
and optionally when:z
is present it must be akeyword
. Additionally::m
allows for arbitrary keys in the map as long as they are strings and their values are strings as well. – Lambder:t "tic"
be valid. So it's either ":x, :y, and maybe :z" OR anything with string keys and values. – cfrick