Skip to content

Commit 7f5e26a

Browse files
authored
Merge pull request #1135 from dzhus/master
Decode map keys into keywords for `[:map` schemas in `json-transformer`
2 parents f8a7308 + 3c9ab67 commit 7f5e26a

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Malli is in well matured [alpha](README.md#alpha).
2020
* **BREAKING**: `:gen/fmap` property requires its schema to create a generator.
2121
* previous behavior defaulted to a `nil`-returning generator, even if the schema doesn't accept `nil`
2222
* use `:gen/return nil` property to restore this behavior
23+
* Support decoding map keys into keywords for `[:map` schemas in `json-transformer` [#1135](https://github.com/metosin/malli/issues/1135)
2324
* FIX: `malli.registry/{mode,type}` not respected in Babashka [#1124](https://github.com/metosin/malli/issues/1124)
2425
* Updated dependencies:
2526

src/malli/transform.cljc

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
(ns malli.transform
22
#?(:cljs (:refer-clojure :exclude [Inst Keyword UUID]))
33
(:require [malli.core :as m]
4+
[malli.util :as mu]
45
[clojure.math :as math]
56
#?(:cljs [goog.date.UtcDateTime])
67
#?(:cljs [goog.date.Date]))
@@ -191,8 +192,11 @@
191192
(catch #?(:clj Exception, :cljs js/Error) _ x))
192193
x))
193194

194-
(defn -transform-map-keys [f]
195-
#(cond->> % (map? %) (into {} (map (fn [[k v]] [(f k) v])))))
195+
(defn -transform-map-keys
196+
([f]
197+
#(cond->> % (map? %) (into {} (map (fn [[k v]] [(f k) v])))))
198+
([ks f]
199+
#(cond->> % (map? %) (into {} (map (fn [[k v]] [(cond-> k (contains? ks k) f) v]))))))
196200

197201
(defn -transform-if-valid [f schema]
198202
(let [validator (m/-validator schema)]
@@ -403,7 +407,9 @@
403407

404408
(defn json-transformer
405409
([] (json-transformer nil))
406-
([{::keys [json-vectors map-of-key-decoders] :or {map-of-key-decoders (-string-decoders)}}]
410+
([{::keys [json-vectors
411+
keywordize-map-keys
412+
map-of-key-decoders] :or {map-of-key-decoders (-string-decoders)}}]
407413
(transformer
408414
{:name :json
409415
:decoders (-> (-json-decoders)
@@ -415,6 +421,13 @@
415421
(-transform-if-valid key-schema)
416422
(-transform-map-keys))
417423
(-transform-map-keys m/-keyword->string))))})
424+
(cond-> keywordize-map-keys
425+
(assoc :map {:compile (fn [schema _]
426+
(let [keyword-keys (->> (mu/keys schema)
427+
(filter keyword?)
428+
(map name)
429+
set)]
430+
(-transform-map-keys keyword-keys -string->keyword)))}))
418431
(cond-> json-vectors (assoc :vector -sequential->vector)))
419432
:encoders (-json-encoders)})))
420433

test/malli/core_test.cljc

+18
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,24 @@
997997
(mt/key-transformer
998998
{:decode #(-> % name (str "_key") keyword)}))))
999999

1000+
(testing "JSON transformer can decode map schema keys"
1001+
(let [schema
1002+
[:map
1003+
[:a :uuid]
1004+
[:b [:enum :x :y :z]]
1005+
["s" :boolean [:enum :f1 :f2]]]
1006+
value
1007+
{"a" "b699671c-d34d-b33f-1337-dbdbfd337e73"
1008+
"b" "x"
1009+
"s" "f1"}
1010+
expected-decoded-value
1011+
{:a #uuid "b699671c-d34d-b33f-1337-dbdbfd337e73"
1012+
:b :x
1013+
"s" :f1}
1014+
decoded-value (m/decode schema value (mt/json-transformer {::mt/keywordize-map-keys true}))]
1015+
(is (= expected-decoded-value decoded-value))
1016+
(is (m/validate schema decoded-value))))
1017+
10001018
(is (= {:x 32}
10011019
(m/decode
10021020
[:map {:decode/string '{:enter #(update % :x inc), :leave #(update % :x (partial * 2))}}

0 commit comments

Comments
 (0)