Fork me on GitHub
#malli
<
2024-04-16
>
Nikolas Pafitis21:04:42

How can i use malli to validate if the value of a map entry is a valid malli schema?

ikitommi07:04:10

you can call (m/schema value) on it at least:

(def Schema [:fn {:error/fn
                  (fn [{:keys [value]} _]
                    (str value " is not a valid Schema"))}
             (m/-safe-pred m/schema)])

(->> :int (m/explain Schema) (me/humanize))
; => nil

(->> :intz (m/explain Schema) (me/humanize))
; => [":intz is not a valid Schema"]

🙌 1
Nikolas Pafitis21:04:13

Specifically i want to check if the form is a valid map schema form

crimeminister21:04:05

I am building a schema based on an external standard that makes a lot of use of inheritance. Certain objects inherit from parent definitions, optionally adding additional attributes. By preference I am using a local registry ("the data way") and would like to be able to capture these relationships in the registry definitions. Naively I imagined I could do something similar to this simplified example:

(def MySchema
  [:schema {:registry {::parent [:map
                                 [:x string?]
                                 [:y number?]]
                       ::child [:merge
                                [:ref ::parent]
                                [:map
                                 [:z boolean?]]]}}
   [:map
    [:foo ::parent]
    [:bar ::child]]])
It seems as though I can't use :merge within the registry, however. I expect I could extract these definitions into separate vars and combine them with (merge) , but perhaps I am missing a more idiomatic approach? Any advice appreciated.

ikitommi07:04:34

I have an experimental branch with map-like schema supporting :extends and :abstract.

🔥 1
ikitommi07:04:00

will polish that at some point and push out for comments.

ikitommi07:04:04

also, you can use :merge with registry, just have to ensure :merge etc. utility schemas are available:

;; add utility schema to global registry
(mr/set-default-registry!
 (mr/composite-registry
  (m/default-schemas)
  (mu/schemas)))

(def MySchema
  (m/schema
   [:schema {:registry {::parent [:map
                                  [:x string?]
                                  [:y number?]]
                        ::child [:merge
                                 [:ref ::parent]
                                 [:map
                                  [:z boolean?]]]}}
    [:map
     [:foo ::parent]
     [:bar ::child]]]))

(mg/sample MySchema)
;({:foo {:x "", :y 2.0}, :bar {:x "", :y -1.0, :z true}}
; {:foo {:x "7", :y -1.0}, :bar {:x "X", :y -0.5, :z true}}
; {:foo {:x "", :y -1}, :bar {:x "", :y 2.0, :z false}}
; {:foo {:x "K", :y 0.75}, :bar {:x "w6", :y 0, :z false}}
; {:foo {:x "", :y 2.5}, :bar {:x "T", :y -1.125, :z false}}
; {:foo {:x "y", :y -11}, :bar {:x "po4", :y 0, :z false}}
; {:foo {:x "0n", :y 1.0}, :bar {:x "36", :y -2.0, :z true}}
; {:foo {:x "8xc", :y -0.875}, :bar {:x "", :y -1.40625, :z false}}
; {:foo {:x "zwSC", :y 51}, :bar {:x "2bHg50G", :y 0.25, :z false}}
; {:foo {:x "oS5", :y 92}, :bar {:x "75rj74", :y -0.453125, :z false}})

ikitommi07:04:23

does that look correct?

crimeminister23:04:52

Thanks for the info @U055NJ5CC! I'll give this a closer look but at a glance it looks correct.

ikitommi07:04:10

you can call (m/schema value) on it at least:

(def Schema [:fn {:error/fn
                  (fn [{:keys [value]} _]
                    (str value " is not a valid Schema"))}
             (m/-safe-pred m/schema)])

(->> :int (m/explain Schema) (me/humanize))
; => nil

(->> :intz (m/explain Schema) (me/humanize))
; => [":intz is not a valid Schema"]

🙌 1