malli

https://github.com/metosin/malli :malli:
pinealan 2021-06-25T01:55:05.223600Z

Hi there! I’m trying to use malli as a parsing+coercion library for external data. I’m a bit lost on what the schemas should look like and what function should I be using. An example is I want to transform a map with shortened key names like this {"a" "11", "b" "10.01"} into this {:ask 11.0 :bid 10.01}. Another case is sequential data, which may look like this ["11" "10.01"], and I would want to get the same data back. I know it’s possible to do some of these steps without malli, i.e. rename-keys or spec/explain with :sequential, but it felt like there should be builtin idioms from the library/schema definitions that helps with the extra transformations that I am performing. Am I just missing something?

ingesol 2021-06-25T07:03:14.224600Z

I’m no expert, but I think you want encode/decode. See https://github.com/metosin/malli#value-transformation. You could write your own custom key-transformer that maintains a mapping of the abbreviations you want.

ingesol 2021-06-25T07:04:46.225600Z

(mt/key-transformer {:encode your-ns/kw->abbr
                     :decode your-ns/abbr->kw})

ingesol 2021-06-25T07:07:57.226700Z

Schema for map would be

[:map-of :keyword :number]
Or whatever more specific number type you want.

ingesol 2021-06-25T07:07:59.226900Z

^^^ @achan961117

ingesol 2021-06-25T07:11:50.227600Z

Something like this in the end (non-tested code)

(m/encode [:map-of :keyword :number]
          {:ask 11.0 :bid 10.01}
          (mt/transformer
           (mt/string-transformer)
           (mt/key-transformer {:encode your-ns/kw->abbr
                                :decode your-ns/abbr->kw})))
;; =>> {"a" "11", "b" "10.01"}

Gary Berger 2021-06-25T13:47:50.230100Z

Hello when using map syntax is there a way of describing a oneOf relationship such that:

[:map
  [:or
    [:opt1 integer?]
    [:opt2 integer?]]]  
will allow either :opt1 or :opt2?

emccue 2021-06-25T13:55:44.231100Z

do you intend that or to be inclusive or exclusive

emccue 2021-06-25T13:57:40.231400Z

[:and
 [:or [:map [:a int?]]
      [:map [:b int?]]]
 [:map [:x int?] [:y int?]]]

emccue 2021-06-25T13:58:13.232100Z

i'm curious if there is a better answer that generates gooder, but this would do the right validation

Gary Berger 2021-06-25T16:15:34.232500Z

exclusive thanks @emccue

ikitommi 2021-06-25T17:09:34.235800Z

@garyberger Usually, :and and :or are the way to go, see example in http://malli.io but there is also a declarative map-keys-relations poc: https://github.com/bsless/malli-keys-relations

👍 2
Gary Berger 2021-06-25T17:35:01.236100Z

Just for clarity and not sure there is an easier way but exclusive or looks like

(m/validate
  [:and
   [:or
    [:map [:p integer?]]
    [:map [:q integer?]]]
   [:not
    [:and
     [:map [:p integer?]]
     [:map [:q integer?]]]]]
  {:p 123 :q 123}) => false