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?
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.
(mt/key-transformer {:encode your-ns/kw->abbr
:decode your-ns/abbr->kw})
Schema for map would be
[:map-of :keyword :number]
Or whatever more specific number type you want.^^^ @achan961117
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"}
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?do you intend that or to be inclusive or exclusive
[:and
[:or [:map [:a int?]]
[:map [:b int?]]]
[:map [:x int?] [:y int?]]]
i'm curious if there is a better answer that generates gooder, but this would do the right validation
exclusive thanks @emccue
@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
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