Fork me on GitHub
#malli
<
2022-09-26
>
erwinrooijakkers15:09:55

Is there a way to describe that a map should contain either one specific key or another key? e.g.

{:foo 1} ; correct
{:bar 1} ; correct
{} ; incorrect, should contain one of :foo or :bar

delaguardo15:09:47

[:or [:map [:foo [:= 1]]] [:map [:bar [:= 1]]]]

erwinrooijakkers15:09:52

yep thanks, 🙂 but there are many more keys in the map so that would be loads of duplication, maybe there’s a way to do ir inside the map

erwinrooijakkers15:09:30

e.g.,

user=> (m/validate [:map [:or [:foo :int]] [:bar :int]] {:quz 1})
Execution error (ExceptionInfo) at malli.core/-fail! (core.cljc:138).
:malli.core/invalid-schema {:schema :x}

hmadelaine16:09:11

You could use a :fn schema for that purpose : It is naive but it works

(def FooOrBar
  [:and
   [:map
    [:foo {:optional true} number?]
    [:bar {:optional true} number?]]
   [:fn
    {:error/message "Only one key must be present"}
    (fn [data]
      (= 1 (count data)))]])


(m/validate FooOrBar {:foo 1}) => true
(m/validate FooOrBar {:bar 1}) => true
(m/validate FooOrBar {:foo 1 :bar 1}) => false
(m/validate FooOrBar {}) => false

pithyless19:09:44

> but there are many more keys in the map so that would be loads of duplication The duplication can be resolved via composition, ala :merge , :union or even :select-keys. Remember also, that you may need to close the map schemas appropriately, if you do not want both :foo and :bar to be valid together. I would prefer :or over :and, since it is more likely to be generator friendly; but you may even consider a version using :multi with custom dispatcher that checks for the existence of certain keys.

darnok14:09:31

@erwinrooijakkers Have you found a solution?

darnok14:09:55

I have similar case, and I tried :and and :or and closing all maps. It doesn't work, because one of the specs won't pass the keys missing in another maps.

robert-stuttaford16:09:34

https://twitter.com/RobStuttaford/status/1574430197079752706 (is it ok for me to paste a link to a tweet like this?)

nice 1
richiardiandrea20:09:51

This is very nice, I wonder if we could do the same with cider...it would be very cool to be able to customize the jump to reference functionality

DrLjótsson20:09:26

I am trying to get swagger-ui to work in reitit but am failing. I just want to double check if reitit + swagger-ui works when malli is used to spec the routes. The docs at https://github.com/metosin/reitit/blob/master/doc/ring/swagger.md say that "Reitit supports https://swagger.io/ documentation, thanks to https://github.com/metosin/schema-tools and https://github.com/metosin/spec-tools., i.e. malli is not mentioned.

DrLjótsson07:09:09

I can confirm that swagger works with malli if reitit.coercion.malli/coercionis used.