malli

David G 2025-06-02T21:29:06.011439Z

Anyone dealt with coercion on multi malli schema where the dispatch value is supposed to be coerced into a keyword? I'm trying to keep my schema serializable (i.e. no function defintions). E.g. I'm getting a invalid dispatch value here:

(require '[malli.core :as malli]
         '[malli.transform :as malli-transform])

(malli/coerce [:multi {:dispatch :type}
               [:a [:map [:type [:enum :a]]]]
               [:b [:map [:type [:enum :b]]]]]
              {:type "a"}
              (malli-transform/transformer
               malli-transform/string-transformer))
I could explicitly update the value to keyword but that'll require an explicit middleware for my server which would probably be too explicit. Any ideas on how to circumvent this?

juhoteperi 2025-06-03T07:57:50.911669Z

IIRC :decode/string from :multi schema level would be applied before multi dispatch [:multi {:decode/string (fn [s] (keyword s)) :dispatch ...} ...]

juhoteperi 2025-06-03T07:58:53.626669Z

Or maybe something like [:and [:map [:type :keyword]] [:multi ...]] so Malli knows before selecting the multi schema that the type property has to be coerced

juhoteperi 2025-06-03T08:00:17.827059Z

Usually :decode/string is the correct choice to apply per-property coercion where the property requires special coercion or the coercion needs to be done before Malli knows the "real" schema for the property (like with :multi)

David G 2025-06-03T15:14:18.709539Z

Yeah dispatching with a fn would work but it won't be serializable anymore. I'll just use strings

David G 2025-06-03T15:14:43.560259Z

The :and might work

juhoteperi 2025-06-03T15:15:14.008659Z

Such simple fns could be evaluated with Sci: https://github.com/metosin/malli?tab=readme-ov-file#persisting-schemas

juhoteperi 2025-06-03T15:15:18.381109Z

but it is an additional dependency

juhoteperi 2025-06-03T15:16:15.534509Z

And hm, https://github.com/metosin/malli?tab=readme-ov-file#serializable-functions, these example are for :fn schema functions, not sure if fns in schema properties, like :decode/string work the same

juhoteperi 2025-06-03T15:16:41.509979Z

But :and version is likely the most "schema as data" approach for this

💯 1
David G 2025-06-03T15:17:20.106449Z

Thanks! I'll try out the :and approach and see if that helps

David G 2025-06-03T15:39:25.861469Z

(require '[malli.core :as malli]
         '[malli.transform :as malli-transform])

(malli/coerce [:and [:map [:type :keyword]] [:multi {:dispatch :type}
                                            [:a [:map [:type [:enum :a]]]]
                                            [:b [:map [:type [:enum :b]]]]]]
              {:type "a"}
              (malli-transform/transformer
               malli-transform/string-transformer))
Works

🎉 1
escherize 2025-06-02T23:20:05.568549Z

it’s probably not “the way” but you can hack it by making the dispatch function turn strings into keywords with (comp keyword :type).