This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-04-10
Channels
- # aleph (3)
- # announcements (1)
- # architecture (16)
- # bangalore-clj (1)
- # beginners (65)
- # biff (5)
- # calva (23)
- # clj-kondo (6)
- # clj-otel (12)
- # clojure-austin (2)
- # clojure-europe (11)
- # clojure-norway (7)
- # clojure-uk (1)
- # clojuredesign-podcast (2)
- # clojurescript (18)
- # conjure (3)
- # datomic (1)
- # deps-new (18)
- # events (1)
- # hyperfiddle (14)
- # java (4)
- # malli (5)
- # off-topic (10)
- # pathom (13)
- # polylith (10)
- # practicalli (1)
- # re-frame (3)
- # reitit (16)
- # releases (1)
- # rum (5)
- # shadow-cljs (17)
Hi everyone, I'm trying to define a custom transformer (not sure if necessary, but felt like what we needed) in 3 different ways. Only one of them works, and I don't really understand why the others don't, could anyone help me understand it a bit more?
(def something-schema [:map
[:something [:or :time/local-date :int]]])
(def transformer1
(mt/transformer
{:name :my-transformer
:default-decoder {:compile (fn [schema _]
(fn [x]
(case (m/form schema)
:time/local-date
(try (-> (time-format/formatter "MM/DD/YYYY")
(time-format/parse x)
(time-coerce/to-long))
(catch Exception _ x))
:int
(try (Integer/parseInt x)
(catch Exception _ x))
x)))}}))
(def transformer2
(mt/transformer
{:name :my-transformer
:decoders {:int (fn [x]
(try (Integer/parseInt x) (catch Exception _ x)))
:time/local-date (fn [x]
(try (-> (time-format/formatter "MM/DD/YYYY")
(time-format/parse x)
(time-coerce/to-long)) (catch Exception _ x)))}}))
(def transformer3
(mt/transformer
{:name :my-transformer
:default-decoder {:compile (fn [schema _]
(fn [x]
(case (m/form schema)
[:or :time/local-date :int] (try
(Integer/parseInt x)
(catch Exception _
(-> (time-format/formatter "MM/DD/YYYY")
(time-format/parse x)
(time-coerce/to-long))))
x)))}}))
(comment
(m/decode
something-schema
{:something "12/12/2012"}
transformer3))
Only transformer3 works the way I wanted it to, the other two just return the same string in the keyword :something
Would anyone know why that's the case?
@U01FK0L87DJ, root cause is that you are returning longs, not LocalDate
instances as your schema defines. Decoding is a process that should always return values that are valid against the schemas.
• in both 1 & 2: :or
selects the first branch that returns valid value. Here, the LocalDate transformation is applied, but an int is returned -> :or
ignores that branch as “invalid” and goes to check the next branch. None of the branches match, so original is returned.
• how to fix?
◦ describe the field type as :int
instead of :time/local-date
◦ mark it somehow as “can be decoded from string”, e.g. via a custom property
◦ something like:
(def something-schema
[:map
[:something [:int {::type :time/local-date}]]])
(def transformer1
(mt/transformer
{:name :my-transformer
:default-decoder {:compile (fn [schema _]
(when (= :time/local-date (::type (m/properties schema)))
(fn [x] (try ...
(catch Exception _ x)))))}}))
Ooooooh I see, that makes sense. Thank you so much!