Hi, may I know if there is a way to decode a referenced [:enum ...] (i.e. via :ref) to its default value? I use :ref for both [:enum ...] and [:map ...] , hence am not sure how to make the default-value-transformer support both cases.
For example:
(def schema1 {:ns/MyMsg [:map {:closed true}
[:int32_val :int]
[:nested_msg [:ref :ns/MyNestedMsg]] ; <--- ref [:map ...]
[:my_enum [:ref :ns/MyEnum]]] ; <--- ref [:enum ...]
:ns/MyNestedMsg [:map {:closed true}
[:string_val :string]]
:ns/MyEnum [:enum
:ZERO :ONE :TWO]})
(def registry1 {:registry (malli.registry/composite-registry
malli.core/default-registry
schema1)})
(def vt1 (malli.transform/default-value-transformer
{:defaults {:int (constantly 0)
:string (constantly "")
:ref (constantly {})}})) ; <--- works for ref [:map ...] only
(malli.core/decode [:ref :ns/MyMsg]
{}
registry1
vt1)
outputs:
{:int32_val 0,
:nested_msg {:string_val ""},
:my_enum {}}
but ideally :my_enum should be :ZERO
{:int32_val 0,
:nested_msg {:string_val ""},
:my_enum :ZERO}hmm... interesting!
arguably default-value-transformer should deref the schemas to see through the :ref, to the default of the underlying schema
here's a workaround:
(def schema-with-defaults {:ns/MyMsg [:map {:closed true}
[:int32_val :int]
[:nested_msg [:ref :ns/MyNestedMsg]]
[:my_enum [:ref :ns/MyEnum]]]
:ns/MyNestedMsg [:map {:closed true :default {:string_val "DEFAULT"}}
[:string_val :string]]
:ns/MyEnum [:enum {:default :ZERO}
:ZERO :ONE :TWO]})
(def registry2 {:registry (malli.registry/composite-registry malli.core/default-registry
schema-with-defaults)})
(def vt3 (malli.transform/default-value-transformer {:defaults {:int (constantly 0)
:ref (fn [schema] (-> schema
malli.core/deref
malli.core/properties
:defaults))}}))
(malli.core/decode [:ref :ns/MyMsg] {} registry2 vt3)
;; ==> {:int32_val 0, :nested_msg {:string_val "DEFAULT"}, :my_enum :ZERO}it needs the :reffed schemas to have explicit :default keys
interestingly, this is only a problem inside maps:
(malli.core/decode [:vector [:ref "bing"]]
[nil]
{:registry (malli.registry/composite-registry malli.core/default-registry
{"bing" :int})}
(malli.transform/default-value-transformer {:defaults {:int (constantly 7)}}))
;; ==> [7]I'll file a bug. I'm not sure what the right solution would be
thanks @joel.kaasinen, appreciate with the filing of bug and the workaround is also very useful for me to experiment with different possibilities. also, jfyi generate function seems to work well with :ref already. hence maybe another possibility is to make generate support generating with default value?
(def schema1 {:ns/MyMsg [:map {:closed true}
[:int32_val :int]
[:nested_msg [:ref :ns/MyNestedMsg]] ; <--- ref [:map ...]
[:my_enum [:ref :ns/MyEnum]]] ; <--- ref [:enum ...]
:ns/MyNestedMsg [:map {:closed true}
[:string_val :string]]
:ns/MyEnum [:enum
:ZERO :ONE :TWO]})
(def registry1 {:registry (malli.registry/composite-registry
malli.core/default-registry
schema1)})
(malli.generator/generate [:ref :ns/MyMsg] registry1)
; {:int32_val 157129, :nested_msg {:string_val "HLFfHa679Q"}, :my_enum :TWO}I think I might have a fix...