Common utilities for working with Prismatic Schema Maps, both Clojure & ClojureScript.
- common Schema definitions:
any-keys
,any-keyword-keys
,open-schema
- schema-aware selectors:
get-in
,select-keys
,select-schema
- schema-aware transformers:
assoc
,dissoc
,assoc-in
,update-in
,update
,dissoc-in
,merge
,optional-keys
,required-keys
- removes the schema name and ns if the schema (value) has changed.
- handle schema default values via
default
&default-coercion-matcher
- meta-data helpers:
schema-with-description
schema-description
,resolve-schema
(clj only),resolve-schema-description
(clj only) - coercion tools:
or-matcher
,map-filter-matcher
,multi-matcher
,coercer
,coerce
- Protocol-based walker for manipulating Schemas in
schema-tools.walk
:walk
,prewalk
andpostwalk
.
Requires Java 1.8.
Normal clojure.core
functions don't work well with Schemas:
(require '[schema.core :as s])
(s/defschema Address {:street s/Str
(s/optional-key :city) s/Str
(s/required-key :country) {:name s/Str}})
;; where's my city?
(select-keys Address [:street :city])
; {:street java.lang.String}
; this should not return the original Schema name...
(s/schema-name (select-keys Address [:street :city]))
; Address
With schema-tools:
(require '[schema-tools.core :as st])
(st/select-keys Address [:street :city])
; {:street java.lang.String, #schema.core.OptionalKey{:k :city} java.lang.String}
(s/schema-name (st/select-keys Address [:street :city]))
; nil
If a given value can't be coerced to match a schema, ex-info is thrown (like schema.core/validate
):
(require '[schema-tools.coerce :as stc])
(def matcher (constantly nil))
(def coercer (stc/coercer String matcher))
(coercer 123)
; clojure.lang.ExceptionInfo: Could not coerce value to schema: (not (instance? java.lang.String 123))
; error: (not (instance? java.lang.String 123))
; schema: java.lang.String
; type: :schema-tools.coerce/error
; value: 123
(coercer "123")
; "123"
; same behavior with coerce (creates coercer on each invocation, slower)
(stc/coerce 123 String matcher)
(stc/coerce "123" String matcher)
Coercion error :type
can be overridden in both cases with an extra argument.
(stc/coerce 123 String matcher :domain/horror)
; clojure.lang.ExceptionInfo: Could not coerce value to schema: (not (instance? java.lang.String 123))
; error: (not (instance? java.lang.String 123))
; schema: java.lang.String
; type: :domain/horror
; value: 123
Filtering out illegal schema keys (using coercion):
(st/select-schema {:street "Keskustori 8"
:city "Tampere"
:description "Metosin HQ" ; disallowed-key
:country {:weather "-18" ; disallowed-key
:name "Finland"}}
Address)
; {:city "Tampere", :street "Keskustori 8", :country {:name "Finland"}}
Filtering out illegal schema map keys using coercion with additional Json-coercion - in a single sweep:
(s/defschema Beer {:beer (s/enum :ipa :apa)})
(def ipa {:beer "ipa" :taste "good"})
(st/select-schema ipa Beer)
; clojure.lang.ExceptionInfo: Could not coerce value to schema: {:beer (not (#{:ipa :apa} "ipa"))}
; data: {:type :schema.core/error,
; :schema {:beer {:vs #{:ipa :apa}}},
; :value {:beer "ipa", :taste "good"},
; :error {:beer (not (#{:ipa :apa} "ipa"))}}
(require '[schema.coerce :as sc])
(st/select-schema ipa Beer sc/json-coercion-matcher)
; {:beer :ipa}
See the tests.
Copyright © 2014-2018 Metosin Oy
Distributed under the Eclipse Public License, the same as Clojure.