diff --git a/src/malli/core.cljc b/src/malli/core.cljc index 11af76d2c..26e9bb84b 100644 --- a/src/malli/core.cljc +++ b/src/malli/core.cljc @@ -231,7 +231,7 @@ (explainer x in acc)) acc explainers))))) (-transformer [this transformer context] - (let [key-transformer (-transformer (map-key) transformer context) + (let [key-transformer (-transformer (map-key this) transformer context) value-transformers (some->> entries (mapcat (fn [[k _ s]] (if-let [t (-transformer s transformer context)] [k t]))) (seq) @@ -783,13 +783,22 @@ (mapcat #(-> % (children opts) (-parse-keys opts) :forms) schemas)))) (schema opts))))))) -(defn map-key [] +(defn map-key [parent-schema] ^{:type ::schema} (reify Schema (-name [_] ::map-key) (-form [_] ::map-key) (-properties [_]) - (-transformer [this transformer context] (-value-transformer transformer this context)))) + (-transformer [this transformer context] + (let [transformer-opts (-transformer-options transformer) + opt-key (case context + :encode :encoders + :decode :decoders) + opts (:opts transformer-opts)] + (if-let [->transformer (some-> transformer-opts + opt-key + ::map-key)] + (->transformer parent-schema opts)))))) ;; ;; registries diff --git a/test/malli/transform_test.cljc b/test/malli/transform_test.cljc index 3b3788f4e..0ab19853e 100644 --- a/test/malli/transform_test.cljc +++ b/test/malli/transform_test.cljc @@ -198,8 +198,23 @@ (deftest key-transformer (let [key-transformer (mt/key-transformer - #(-> % name (str "_key") keyword) - #(-> % name (str "_key")))] + #(-> % name (str "_key") keyword) + #(-> % name (str "_key"))) + + schema-aware-key-fn (fn [schema opts] + (is (= [:x :y [:opt :z]] + (vec (map first (m/children schema))))) + (is (nil? opts)) + #(name %)) + + schema-aware-key-transformer (mt/transformer + {:name ::custom + :encoders {::m/map-key schema-aware-key-fn}})] + (testing "schema-aware-key-fn" + (is (= {"x" 18 "y" "john" "a" "doe"} + (m/encode [:map [:x int?] [:y string?] [[:opt :z] boolean?]] + {:x 18 :y "john" :a "doe"} + schema-aware-key-transformer)))) (testing "decode" (is (= {:x_key 18 :y_key "john" :a_key "doe"} (m/decode [:map [:x int?] [:y string?] [[:opt :z] boolean?]]