metosin / malli

High-performance data-driven data specification library for Clojure/Script.
Eclipse Public License 2.0
1.44k stars 204 forks source link

Decoding with seqexp doesn't decode numbers properly #958

Open Coder-DG opened 9 months ago

Coder-DG commented 9 months ago

I'm getting some weird errors with my schema with the decoder/transformers and :+ and would love if someone can help me figure this out (commented inside the code block):

(require '[malli.core :as m]
         '[malli.transform :as mt])

;; Malli doesn't seem to have a type that can be decoded for bigdec hence this more elaborate schema
(def bigdec-s (malli/-simple-schema
               {:type :core/bigdec
                :pred (partial instance? BigDecimal)
                :type-properties
                {:decode/json (fn [x]
                                (try (bigdec x)
                                     (catch Exception _ x)))}}))

;; :+ doesn't work
(m/decode [:+ [:and bigdec-s pos?]]
          ["0"]
          (mt/transformer
           (mt/key-transformer {:decode keyword})
           mt/json-transformer))
;; => ["0"]

;; :vector does work
(m/decode [:vector {:min 1} [:and bigdec-s pos?]]
          ["0"]
          (mt/transformer
           (mt/key-transformer {:decode keyword})
           mt/json-transformer))
;; => [0M]

What's concerning is that m/explain just throws an exception (also does m/coerce):

(m/explain [:+ [:and bigdec-s pos?]]
           (m/decode [:+ [:and bigdec-s pos?]]
                     ["0"]
                     (mt/transformer
                      (mt/key-transformer {:decode keyword})
                      mt/json-transformer)))
;; => Execution error (ClassCastException) at malli.core/-simple-schema$reify$reify$explain (core.cljc:658).
;;    class java.lang.String cannot be cast to class java.lang.Number (java.lang.String and java.lang.Number are in module java.base of loader 'bootstrap')

(m/explain [:vector {:min 1} [:and bigdec-s pos?]]
           (m/decode [:vector {:min 1} [:and bigdec-s pos?]]
                     ["0"]
                     (mt/transformer
                      (mt/key-transformer {:decode keyword})
                      mt/json-transformer)))
;; => {:schema [:vector [:and :core/bigdec pos?]],
;;     :value [0M],
;;     :errors ({:path [0 1], :in [0], :schema pos?, :value 0M})}