I'm struggling somewhat to understand how to set up a custom coercion in schema.
I want a schema and coercion that wants to accept a string "2020-03-18"
and coerces it to a LocalDate
we do that at the json layer with 'cheshire.generate/add-encoder'
err sorry that's for serialization, you want coercion
we use 'ring.swagger.coerce/coerce'
(defmethod coerce/time-matcher LocalDate
[_]
#(if (jt/local-date? %)
%
(try
(jt/local-date local-date-format %)
(catch Exception original-exc
(let [result (try-parse-as-date %)]
(if (nil? result)
(throw original-exc)
result))))))
@braden.shepherdson just opened a old project which uses Schema + Joda, mapping look like this:
;;
;; joda-time
;;
(defn ->DateTime [date] (if (instance? Date date) (tc/from-date date) date))
(defn parse-date-time ^DateTime [date] (tf/parse (tf/formatters :date-time-parser) (->DateTime date)))
(defn parse-date ^DateTime [date] (tf/parse-local-date (tf/formatters :date) (->DateTime date)))
(defn parse-time ^DateTime [date] (tf/parse-local-time (tf/formatters :time-parser) (->DateTime date)))
(defmethod schema-tools.swagger.core/transform-type DateTime [_ _] {:type "string" :format "date-time"})
(defmethod schema-tools.swagger.core/transform-type LocalDate [_ _] {:type "string" :format "date"})
(defmethod schema-tools.swagger.core/transform-type LocalTime [_ _] {:type "string" :format "time"})
;;
;; helpers
;;
(defn cond-matcher [preds]
(fn [x]
(or
(some
(fn [[f1 f2]]
(if (f1 x) (f2 x)))
preds)
x)))
(def keyword->int
{s/Int (cond-matcher
{string? stc/string->long
number? sc/safe-long-cast
keyword? (fn [x]
(try
(Long/valueOf (name x))
(catch Exception _ x)))})})
(def keyword->string
{String (cond-matcher {keyword? name})})
(def string->joda
{DateTime (cond-matcher {string? parse-date-time})
LocalDate (cond-matcher {string? parse-date})
LocalTime (cond-matcher {string? parse-time})})
(def json-coercion-matcher
(some-fn keyword->int keyword->string string->joda stc/json-coercion-matcher))
(def string-coercion-matcher
(some-fn keyword->int keyword->string string->joda stc/string-coercion-matcher))
another example of custom coercion - what about forcing things to uppercase or lowercase?
I'm not super concerned about that since this is an API intended to be target by my own code, but still.