Malli
Malli is popular for web APIs (used by Reitit for request/response coercion), with JSON Schema/OpenAPI export, schema registries, and good performance. Alternatives: spec, Plumatic Schema.
(require '[malli.core :as m]
'[malli.error :as me]
'[malli.generator :as mg]
'[malli.transform :as mt])
;; Schemas are data
(def User
[:map
[:id :uuid]
[:name [:string {:min 1}]]
[:age [:int {:min 0 :max 150}]]
[:email {:optional true} [:re #".+@.+\..+"]]
[:roles [:set [:enum :admin :editor :viewer]]]])
(m/validate User {:id (random-uuid) :name "Ana" :age 30 :roles #{:admin}}) ; true
(-> (m/explain User {:id 1 :name "" :age -1 :roles #{}})
(me/humanize))
;; {:id ["should be a uuid"], :name ["should be at least 1 character"], :age ["should be at least 0"]}
;; Coercion (e.g., from JSON/HTTP strings)
(m/decode [:map [:age :int]] {:age "42"} mt/string-transformer) ; {:age 42}
;; Generation
(mg/generate User)
;; Function schemas
(def add-schema [:=> [:cat :int :int] :int])
(m/validate add-schema +) ; validates function schemas via generative testing