tur/schema
runtime schema validation for untyped boundary data.
Since: Phase SC0
schema/str
(schema/str :)
a schema that matches JSON strings (:cstr).
A scalar string schema; decodes to the underlying cstr.
(schema-decode (schema/str) (json/string "hi")) ; => ok("hi")
Since: Phase SC0
schema/int
(schema/int :)
a schema that matches JSON integers (:int).
A scalar int schema; decodes to the underlying int.
(schema-decode (schema/int) (json/int 42)) ; => ok(42)
Since: Phase SC0
schema/float
(schema/float :)
a schema that matches JSON floats (:float).
A scalar float schema; decodes to the underlying float bits.
Since: Phase SC0
schema/bool
(schema/bool :)
a schema that matches JSON booleans (:bool).
A scalar bool schema; decodes to 0 or 1.
Since: Phase SC0
schema/nil
(schema/nil :)
a schema that matches JSON null.
A null schema; decodes to 0.
Since: Phase SC0
schema/literal-int
(schema/literal-int [v : int] :)
a schema matching one exact integer value.
| v | the required int value |
A literal schema; decodes to v only when the node is exactly v.
(schema-decode (schema/literal-int 7) (json/int 7)) ; => ok(7)
Since: Phase SC0
schema/literal-str
(schema/literal-str [v : cstr] :)
a schema matching one exact string value.
| v | the required cstr value |
A literal schema; decodes to v only when the node string equals v.
(schema-decode (schema/literal-str "active") (json/string "active"))
Since: Phase SC0
schema/object-new
(schema/object-new :)
start an empty object schema.
An object schema with no fields yet; add fields with schema/field.
(schema/field (schema/field (schema/object-new)
"name" (schema/str))
"age" (schema/int))
Since: Phase SC1
schema/field
(schema/field [obj : int key : cstr inner : int] :)
add a declared field to an object schema.
| obj | an object schema (from schema/object-new) | |
| key | the field name | |
| inner | the schema the field value must satisfy. Wrap it in | |
| schema/optional to allow the field to be absent or null. |
The same object schema, with the field appended (mutated in place).
(schema/field (schema/object-new) "name" (schema/str))
Since: Phase SC1
schema/array
(schema/array [elem : int] :)
a schema for a homogeneous JSON array.
| elem | the schema each element must satisfy |
An array schema; decodes to a Vec of decoded element values.
(schema/array (schema/int)) ; matches [1, 2, 3]
Since: Phase SC2
schema/optional
(schema/optional [inner : int] :)
a schema where null / absent is acceptable.
| inner | the schema a present, non-null value must satisfy |
An optional schema; decodes to the inner value, or 0 when null. Inside schema/object, an optional field may also be absent entirely.
(schema/optional (schema/str))
Since: Phase SC2
schema/union
(schema/union [arms : int] :)
a schema where the first matching arm wins.
| arms | a Vec of schemas; tried left to right |
A union schema; decodes to the value from the first arm that matches. If no arm matches, all arms' errors are reported.
(schema/union (vec-of (schema/int) (schema/str)))
Since: Phase SC2
schema/transform
(schema/transform [inner : int ^fat f] :)
decode with a schema, then map the result.
| inner | the schema to decode with | |
| f | a function or *capturing closure* applied to the decoded value | |
| (only on success); carried as a fat closure (^fat) |
A transform schema; decodes to (f decoded-inner).
(schema/transform (schema/int) (fn [x] (* x 2))) (let [k 100] (schema/transform (schema/int) (fn [x] (+ x k)))) ; captures k
Since: Phase SC2
schema/rec
(schema/rec [f] :)
a self-referential schema for recursive data.
| f | a function taking the recursive schema itself (self) and | |
| returning the schema body, e.g. | ||
| (fn [self] (schema/field (schema/object-new) | ||
| "children" (schema/array self))) |
A recursive schema. The body is forced (by calling f with self) on first decode and memoized thereafter.
(schema/rec (fn [self]
(schema/field
(schema/field (schema/object-new) "value" (schema/int))
"children" (schema/array self))))
Since: Phase SC4
schema/kind
(schema/kind [s : int] :)
return the SCHEMA_* discriminant of a schema value.
| s | a schema value |
The integer discriminant (SCHEMA_STR .. SCHEMA_REC).
Since: Phase SC0
schema/always
(schema/always [value : int] :)
a pure schema that ignores its input, decoding to a fixed value.
| value | the value (an int-carrier; e.g. an int, a cstr ptr, or a | |
| top-level function pointer) the schema always decodes to |
An always-succeeds schema; decoding it never inspects the node.
(schema-decode! (schema/always 42) (json/null)) ; => 42
Since: Phase SC7
schema/never
(schema/never [message : cstr] :)
the empty schema: always fails with a fixed message (identity of schema/union).
| message | the failure message reported at the current path |
An always-fails schema.
(schema-decode (schema/never "no match") (json/int 1)) ; => err
Since: Phase SC7
schema/ap
(schema/ap [sf : int sa : int] :)
the Validation applicative: apply sf's decoded function to sa's decoded value, accumulating both arms' errors.
| sf | a schema decoding to a unary function pointer (a/the result of | |
| schema/always over a top-level, non-capturing function) | ||
| sa | a schema decoding to that function's argument |
An applicative schema decoding to (f a). NOTE: the decoded function is applied via a direct C call, so it must be a top-level (non-capturing) function -- multi-argument currying needs closures and is deferred.
;; double-it is a top-level (defn double-it [x] (* x 2))
(schema/ap (schema/always double-it)
(schema/field-of "n" (schema/int)))
Since: Phase SC7
schema/field-of
(schema/field-of [key : cstr inner : int] :)
decode a JSON object and extract one key's decoded value via an inner schema.
| key | the object key to extract | |
| inner | the schema the key's value must satisfy. Wrap in schema/optional | |
| to allow the key to be absent. |
A field-extract schema decoding to the inner decoded value.
(schema/field-of "age" (schema/int)) ; on {"age":30} => 30
Since: Phase SC7
schema/fmap
(schema/fmap [inner : int ^fat f] :)
the Functor map for schemas: decode with `inner`, then map the result with `f` (alias for schema/transform).
| inner | the schema to decode with | |
| f | a function or capturing closure applied to the decoded value on | |
| success; carried as a fat closure (^fat) |
A schema decoding to (f decoded-inner).
(schema/fmap (schema/int) double-it)
Since: Phase SC7
schema/alt
(schema/alt [a : int b : int] :)
the Alternative `<|>`: a two-arm first-match union (try `a`, then `b`).
| a | the first schema to try | |
| b | the schema to try if a does not match |
A union schema over the two arms.
(schema/alt (schema/int) (schema/str))
Since: Phase SC7
schema/ap-fat
(schema/ap-fat [sf : int sa : int] :)
closure-aware Validation applicative (kind 16).
| sf | a schema decoding to a unary fat-closure handle | |
| sa | a schema decoding to that closure's argument |
An applicative schema decoding to (f a).
Since: Phase SC7
Schema
(defstruct Schema [A])
phantom wrapper over an int-carrier schema, for HKT dispatch.
| A | phantom: the type a successful decode produces | |
| raw | the underlying SC0 schema pointer (int-carrier) |
Since: Phase SC7
Functor[Schema]
(definstance Functor [Schema])
map a function over a schema's decoded value.
Applicative[Schema]
(definstance Applicative [Schema])
Validation applicative: pure + accumulating ap.
Alternative[Schema]
(definstance Alternative [Schema])
first-match choice (`alt-or`) + the empty schema.
schema-error-path
(schema-error-path [e : int] :)
the dot-separated field path of a SchemaError.
| e | a SchemaError value |
The path cstr, e.g. "user.address.zip" (empty string at the root).
Since: Phase SC3
schema-error-text
(schema-error-text [e : int] :)
the human-readable message of a SchemaError.
| e | a SchemaError value |
The message cstr, e.g. "expected :cstr, got :int".
Since: Phase SC3
schema-error-count
(schema-error-count [errs : int] :)
number of errors in an error Vec.
| errs | a Vec of SchemaError (the err payload of schema-decode) |
The error count (0 if errs is null).
Since: Phase SC3
schema-error-at
(schema-error-at [errs : int i : int] :)
the i-th SchemaError in an error Vec.
| errs | a Vec of SchemaError | |
| i | zero-based index |
The SchemaError at index i (0 if out of bounds).
Since: Phase SC3
schema-error-message
(schema-error-message [errs : int] :)
format an error Vec into one human-readable cstr.
| errs | a Vec of SchemaError |
A newline-separated string, one "path: message" line per error (a root-level error omits the leading "path: "). Caller owns the cstr.
(schema-error-message errs) ; => "user.age: expected :int, got :cstr"
Since: Phase SC3
sch-vpush-
(sch-vpush- [v : ptr x : int] :)
validate a JSON node against a schema.
| schema | a schema value (from the constructors above) | |
| node | a JSON node (from json/decode or #json(...)) |
Result<ptr<void>, Vec<SchemaError>>. On success, ok holds the decoded value (see the module docstring for the per-kind result shape). On failure, err holds a Vec of every accumulated SchemaError -- decoding does not stop at the first violation.
(let [s (schema/field (schema/object-new) "age" (schema/int))
r (schema-decode s (json/decode "{\"age\":1}"))]
(schema-decode-ok? r)) ; => true
Since: Phase SC1
sch-push-err-
(sch-push-err- [errs : ptr path : cstr msg : cstr val : int] :)
sch-mkpath-
(sch-mkpath- [base : cstr key : cstr] :)
sch-mkidx-
(sch-mkidx- [base : cstr idx : int] :)
sch-tyname-
(sch-tyname- [jtype : int] :)
sch-want-name-
(sch-want-name- [kind : int] :)
sch-jtype-
(sch-jtype- [n : int] :)
sch-jpayload-
(sch-jpayload- [n : int] :)
sch-decode-rec-
(sch-decode-rec- [schema : int node : int path : cstr errs : ptr] :)
schema-decode
(schema-decode [schema : int node : int] :)
schema-decode-ok?
(schema-decode-ok? [r : int] :)
whether a schema-decode Result succeeded.
| r | the Result from schema-decode |
true if decoding succeeded, false otherwise.
Since: Phase SC1
schema-decode-value
(schema-decode-value [r : int] :)
the decoded value of a successful Result.
| r | the Result from schema-decode (must be ok) |
The decoded value (see the module docstring for per-kind shape).
Since: Phase SC1
schema-decode-errors
(schema-decode-errors [r : int] :)
the error Vec of a failed Result.
| r | the Result from schema-decode (must be err) |
The Vec of SchemaError (0 if r is ok).
Since: Phase SC1
schema-decode-abort
(schema-decode-abort [errs : int] :)
internal: print an error Vec to stderr and abort.
schema-decode!
(schema-decode! [schema : int node : int] :)
decode against a schema, panicking on any violation.
| schema | a schema value | |
| node | a JSON node |
The decoded value. Aborts with the formatted error message if the value does not satisfy the schema -- use only for trusted data / tests.
(schema-decode! (schema/int) (json/int 5)) ; => 5
Since: Phase SC1