Specter's been very nice for cleaning up custom #malli transformers, a lot of recursive assoc-ing and dissoc-ing that's easily replaced by setval/`transform`, with some filterering for fancier property-based work
(defn kv-filterer
"Navigates like filterer when both k-fn (called on key) and v-fn (called on val)
return truthy."
[k-fn v-fn]
(path (filterer (fn [[k v]] (and (k-fn k) (v-fn v))))))
(defn- where-property
([prop] (path [(selected? 1 prop identity)]))
([prop f] (path [(selected? 1 prop f)])))
(defn strip-nil-optional-keys-transformer
"A decoding transformer, only mounting to :map schemas, which dissocs all `:optional` keys with a nil value."
[& {:as _opts}]
(mt/transformer
{:decoders
{:map
{:compile
(fn [schema _]
(let [optionals (->> schema
(m/children)
(select [ALL (where-property :optional true?) FIRST])
(set))]
{:leave (fn [m]
(setval [map? (kv-filterer optionals nil?) ALL] NONE m))}))}}}))