Extension of schema for input coercion (coercing an input to match a schema)
Extension of schema for input coercion (coercing an input to match a schema)
A library for data shape definition and validation. A Schema is just Clojure data, which can be used to document and validate Clojure functions and data.
For example,
(def FooBar {:foo Keyword :bar [Number]}) ;; a schema
(check FooBar {:foo :k :bar [1.0 2.0 3.0]}) ==> nil
representing successful validation, but the following all return helpful errors describing how the provided data fails to measure up to schema FooBar's standards.
(check FooBar {:bar [1.0 2.0 3.0]}) ==> {:foo missing-required-key}
(check FooBar {:foo 1 :bar [1.0 2.0 3.0]}) ==> {:foo (not (keyword? 1))}
(check FooBar {:foo :k :bar [1.0 2.0 3.0] :baz 1}) ==> {:baz disallowed-key}
Schema lets you describe your leaf values using the Any, Keyword, Symbol, Number, String, and Int definitions below, or (in Clojure) you can use arbitrary Java classes or primitive casts to describe simple values.
From there, you can build up schemas for complex types using Clojure syntax (map literals for maps, set literals for sets, vector literals for sequences, with details described below), plus helpers below that provide optional values, enumerations, arbitrary predicates, and more.
Assuming you (:require [schema.core :as s :include-macros true]), Schema also provides macros for defining records with schematized elements (s/defrecord), and named or anonymous functions (s/fn and s/defn) with schematized inputs and return values. In addition to producing better-documented records and functions, these macros allow you to retrieve the schema associated with the defined record or function. Moreover, functions include optional validation, which will throw an error if the inputs or outputs do not match the provided schemas:
(s/defrecord FooBar [foo :- Int bar :- String])
(s/defn quux :- Int [foobar :- Foobar mogrifier :- Number] (* mogrifier (+ (:foo foobar) (Long/parseLong (:bar foobar)))))
(quux (FooBar. 10 "5") 2) ==> 30
(fn-schema quux) ==> (=> Int (record user.FooBar {:foo Int, :bar java.lang.String}) java.lang.Number)
(s/with-fn-validation (quux (FooBar. 10.2 "5") 2)) ==> Input to quux does not match schema: [(named {:foo (not (integer? 10.2))} foobar) nil]
As you can see, the preferred syntax for providing type hints to schema's defrecord, fn, and defn macros is to follow each element, argument, or function name with a :- schema. Symbols without schemas default to a schema of Any. In Clojure, class (e.g., clojure.lang.String) and primitive schemas (long, double) are also propagated to tag metadata to ensure you get the type hinting and primitive behavior you ask for.
If you don't like this style, standard Clojure-style typehints are also supported:
(fn-schema (s/fn [^String x])) ==> (=> Any java.lang.String)
You can directly type hint a symbol as a class, primitive, or simple schema.
See the docstrings of defrecord, fn, and defn for more details about how to use these macros.
A library for data shape definition and validation. A Schema is just Clojure data, which can be used to document and validate Clojure functions and data. For example, (def FooBar {:foo Keyword :bar [Number]}) ;; a schema (check FooBar {:foo :k :bar [1.0 2.0 3.0]}) ==> nil representing successful validation, but the following all return helpful errors describing how the provided data fails to measure up to schema FooBar's standards. (check FooBar {:bar [1.0 2.0 3.0]}) ==> {:foo missing-required-key} (check FooBar {:foo 1 :bar [1.0 2.0 3.0]}) ==> {:foo (not (keyword? 1))} (check FooBar {:foo :k :bar [1.0 2.0 3.0] :baz 1}) ==> {:baz disallowed-key} Schema lets you describe your leaf values using the Any, Keyword, Symbol, Number, String, and Int definitions below, or (in Clojure) you can use arbitrary Java classes or primitive casts to describe simple values. From there, you can build up schemas for complex types using Clojure syntax (map literals for maps, set literals for sets, vector literals for sequences, with details described below), plus helpers below that provide optional values, enumerations, arbitrary predicates, and more. Assuming you (:require [schema.core :as s :include-macros true]), Schema also provides macros for defining records with schematized elements (s/defrecord), and named or anonymous functions (s/fn and s/defn) with schematized inputs and return values. In addition to producing better-documented records and functions, these macros allow you to retrieve the schema associated with the defined record or function. Moreover, functions include optional *validation*, which will throw an error if the inputs or outputs do not match the provided schemas: (s/defrecord FooBar [foo :- Int bar :- String]) (s/defn quux :- Int [foobar :- Foobar mogrifier :- Number] (* mogrifier (+ (:foo foobar) (Long/parseLong (:bar foobar))))) (quux (FooBar. 10 "5") 2) ==> 30 (fn-schema quux) ==> (=> Int (record user.FooBar {:foo Int, :bar java.lang.String}) java.lang.Number) (s/with-fn-validation (quux (FooBar. 10.2 "5") 2)) ==> Input to quux does not match schema: [(named {:foo (not (integer? 10.2))} foobar) nil] As you can see, the preferred syntax for providing type hints to schema's defrecord, fn, and defn macros is to follow each element, argument, or function name with a :- schema. Symbols without schemas default to a schema of Any. In Clojure, class (e.g., clojure.lang.String) and primitive schemas (long, double) are also propagated to tag metadata to ensure you get the type hinting and primitive behavior you ask for. If you don't like this style, standard Clojure-style typehints are also supported: (fn-schema (s/fn [^String x])) ==> (=> Any java.lang.String) You can directly type hint a symbol as a class, primitive, or simple schema. See the docstrings of defrecord, fn, and defn for more details about how to use these macros.
Schemas representing abstract classes and subclasses
Schemas representing abstract classes and subclasses
(Extremely) experimental support for 'completing' partial datums to match a schema. To use it, you must provide your own test.check dependency.
(Extremely) experimental support for 'completing' partial datums to match a schema. To use it, you must provide your own test.check dependency.
(Very) experimental support for compiling schemas to test.check generators. To use it, you must provide your own test.check dependency.
TODO: add cljs support.
(Very) experimental support for compiling schemas to test.check generators. To use it, you must provide your own test.check dependency. TODO: add cljs support.
Macros and macro helpers used in schema.core.
Macros and macro helpers used in schema.core.
Features that require an explicit potemkin dependency to be provided by the consumer.
Features that require an explicit potemkin dependency to be provided by the consumer.
A collection spec represents a collection of elements, each of which is itself schematized.
A collection spec represents a collection of elements, each of which is itself schematized.
Protocol and preliminaries for Schema 'specs', which are a common language for schemas to use to express their structure.
Protocol and preliminaries for Schema 'specs', which are a common language for schemas to use to express their structure.
Utilities for testing with schemas
Utilities for testing with schemas
Private utilities used in schema implementation.
Private utilities used in schema implementation.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close