Using prismatic/schema coerce is it possible to have default values when the coercion fails instead of the error message.
I have a value in a csv file which could be blank (nil) or s/Int. At the moment with the below code I get this for blanks:
#schema.utils.ErrorContainer{:error (not (integer? nil))}
code:
(def answers (slurp "excel/answers.csv"))
(def answers-field-schemas [s/Int s/Int s/Str s/Str s/Str s/Int s/Str s/Int s/Str s/Int s/Str s/Int s/Str s/Int s/Str])
(def answers-field-coercers
(mapv coerce/coercer
answers-field-schemas
(repeat coerce/string-coercion-matcher)))
(defn answers-coerce-fields [fields]
(mapv #(%1 %2) answers-field-coercers fields))
(def answers->data (map answers-coerce-fields (csv/parse-csv answers :end-of-line "\r")))
1 . Error you get is not coercion error, but validation error. Values must conform initial schema.
2 . To fix it, you need to loose your schema for fields that may be nil
. Let's say it's second field:
(def answers-field-schemas [s/Int (s/maybe s/Int) ...])
At this point you will get nil
s instead of errors for nil
fields:
user> (answers-coerce-fields ["1" nil])
[1 nil]
3 . If you really want default values instead of nil
s after coercion, you will need custom coercion matcher. Something like this:
(import 'schema.core.Maybe)
(defn field-matcher-with-default [default]
(fn [s]
(let [string-coercion-fn (or (coerce/string-coercion-matcher s)
identity)
maybe-coercion-fn (if (instance? schema.core.Maybe s)
(fnil identity default)
identity)]
(comp
string-coercion-fn
maybe-coercion-fn))))
Also modify previous coercers as follows:
(def answers-field-coercers
(mapv coerce/coercer
answers-field-schemas
;; your default here
(repeat (field-matcher-with-default -1))))
and then:
user> (answers-coerce-fields ["1" nil])
[1 -1]
Note that default value must conform schema as well, so it's not possible to set default value of type String
for schema (s/maybe s/Int)
.