Fork me on GitHub
#malli
<
2021-06-25
>
pinealan01:06:05

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?

ingesol07:06:14

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.

ingesol07:06:46

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

ingesol07:06:57

Schema for map would be

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

ingesol07:06:50

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 Berger13:06:50

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?

emccue13:06:44

do you intend that or to be inclusive or exclusive

emccue13:06:40

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

Gary Berger17:06:01

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

emccue13:06:13

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

ikitommi17:06:34

@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

👍 4