Skip to content

Instantly share code, notes, and snippets.

@mwmitchell
Created December 14, 2012 16:22
Show Gist options
  • Save mwmitchell/4286647 to your computer and use it in GitHub Desktop.
Save mwmitchell/4286647 to your computer and use it in GitHub Desktop.
clojure validation and transform function
;; Validation and transformation handling of input maps.
;; Provides input validation, transform, and output validation capabilities
;; Allows input values to be marked as required or not by setting required error message
(letfn [(check! [value fun-msg-pairs]
(when (seq fun-msg-pairs)
(doall (for [[f m] (partition 2 fun-msg-pairs)]
(when-not (f value) (throw (Exception. m)))))))]
(defn validate-using [spec input]
(reduce (fn [m [k item-spec]]
(cond
(map? item-spec)
(assoc m k (validate-using item-spec input))
(vector? item-spec)
(let [[val-fun req-msg in-checker-pairs transformer out-checker-pairs] item-spec]
(if-let [value (val-fun input)]
(do
(check! value in-checker-pairs)
(let [t-value (or (and transformer (transformer value)) value)]
(check! t-value out-checker-pairs)
(assoc m k t-value)))
(if req-msg (throw (Exception. req-msg)))))
(or (keyword? item-spec) (fn? item-spec))
(assoc m k (item-spec input))))
{}
spec)))
;; sample usage:
(let [my-spec {:id [ ;; the function to use for extracting the value from the input map:
:ID
;; required message
":id is required"
;; input validation and error message pairs
[#(re-find #"^[0-9]+$" %) "must be a number"]
;; transforming function
#(Integer/parseInt %)
;; output (post transform) validation and error pairs
[#(> % 5) "must be > 5"]]
:codez [:CODE_LIST nil nil (comp set #(clojure.string/split % #","))
[#(not (% "1")) "1 is not allowed"]]
:address {:number [:ADDR nil nil #(re-find #"[0-9]+" %)]
:street [:ADDR nil nil #(re-find #"[a-z]+" %)]
:city :acs}
;; no validation/transofmration, just mapping
:name :YOUR_NAME
}
input { ;; nothing special, straight mapping if present
:YOUR_NAME "sally"
;; not required, just transformed
:ADDR "123 abc street"
;; try adding 1 here
:CODE_LIST "56,10"
;; make this less than 6
:ID "6"}]
(prn (validate-using my-spec input)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment