| • Intro | ||
| • Installation | ||
| • Usage | ||
| • Schema types | ||
| • Data generation | ||
| • Reference | ||
| • Index |
Next: Installation, Previous: Top, Up: Top [Contents][Index]
Generic purpose schema library for serialization and validation of data.
This library is used by CL-REST-SERVER for API serialization and validation.
It features:
With Quicklisp:
(ql:quickload "schemata")
Next: Schema types, Previous: Installation, Up: Top [Contents][Index]
Use DEFSCHEMAfor defining schemas.
Schema example:
(schemata:defschema customer
(object "customer"
((id string :external-name "id" :accessor
customer-id :documentation "customer id")
(number string :external-name "number" :required nil
:accessor customer-nr :documentation
"customer number")
(name string :external-name "name" :accessor
customer-name :documentation "customer name")
(address-1 string :external-name "address1"
:required nil :documentation
"customer first address")
(address-2 string :external-name "address2"
:required nil :documentation
"customer second address")
(postal-code string :external-name "postalcode"
:required nil :documentation
"postal code")
(postal-area string :external-name "postalarea"
:required nil :documentation
"postal area")
(country string :external-name "country" :required nil
:documentation "country code")
(phone string :external-name "phone" :required nil
:documentation "phone")
(fax string :external-name "fax" :required nil
:documentation "fax")
(email string :external-name "email" :required nil
:documentation "email"))
(:documentation "customer data fetched")))
Use VALIDATE-WITH-SCHEMA.
Via generic-serializer library.
(with-output-to-string (s)
(gs:with-serializer-output s
(gs:with-serializer :json
(serialize-with-schema *schema* user))))
(with-output-to-string (s)
(gs:with-serializer-output s
(gs:with-serializer :json
(serialize-with-schema
(find-schema 'user-schema) *user*))))
(unserialize-with-schema
(find-schema 'user-schema)
(json:decode-json-from-string data)
:json)
See PATCH-WITH-SCHEMAand POPULATE-WITH-SCHEMA.
Next: Data generation, Previous: Usage, Up: Top [Contents][Index]
Schemas can be built from Common Lisp types:
SCHEMATA> (defparameter *s* (schema string))
*S*
SCHEMATA> *s*
#<TYPE-SCHEMA STRING {1006FBBD13}>
SCHEMATA> (validate-with-schema *s* "22")
NIL
SCHEMATA> (validate-with-schema *s* 22 :error-p nil)
#<VALIDATION-ERROR "~s is not of type: ~a" {100152EB13}>
Object schemas are built using the syntax: (object name attributes options).
Attributes are specified as: (attribute-name attribute-type &rest options).
The attribute-type is parsed as a schema.
Possible attribute options are: ‘required‘, ‘required-message‘, ‘default‘, ‘accessor‘, ‘writer‘, ‘reader‘, ‘parser‘, ‘validator‘, ‘add-validator‘, ‘formatter‘, ‘external-name‘, ‘serializer‘, ‘unserializer‘, ‘slot‘.
Example:
SCHEMATA> (schema (object person
((name string)
(age integer :required nil))))
#<OBJECT-SCHEMA {1001843543}>
Schema for lists with elements of certain type/schema.
Syntax: (list-of list-element-schema)
Examples:
(schema (list-of string))
(schema (list-of (or string number)))
SCHEMATA> (defparameter *s* (schema (list-of integer)))
*S*
SCHEMATA> (validate-with-schema *s* '(1 2 "foo"))
; Evaluation aborted on #<SCHEMATA:VALIDATION-ERROR "~s is not of type: ~a" {1006ECA323}>.
SCHEMATA> (validate-with-schema *s* '(1 2 3))
NIL
Schema for list with all its elements specified with schemas.
Syntax: (list &rest schemas)
Examples:
(schema (list string number boolean))
Schema for association lists with certain type of keys and values.
Syntax: (alist-of (key-schema . value-schema))
Examples:
(schema (alist-of (keyword . string)))
Schema for association lists with certain keys and values.
Syntax: (alist association-list &rest options)
where association-list is a list of conses with key and schema.
Options can be :required, :optional and :allow-other-keys.
Examples:
(schema (alist ((:x . string)(:y . number))))
(schema (alist ((:x . string)(:y . number)) :optional (:y)))
Schema for property lists with certain type of keys and values.
Syntax: (plist-of key-schema value-schema)
Examples:
(schema (plist-of keyword string))
Schema for property lists with certain keys and values.
Syntax: (plist property-list &rest options)
where property-list specifies the schemas for the keys.
Options can be :required, :optional and :allow-other-keys.
Examples:
(schema (plist (:x string :y number)))
(schema (plist (:x string :y number) :optional (:y)))
Schema for hash-tables with certain type of keys and values.
Syntax: (hash-table-of key-schema value-schema)
Examples:
(schema (hash-table-of keyword string))
Schema for property lists with certain keys and values.
Syntax: (hash-table property-list &rest options)
where property-list specifies the schemas for the keys and values.
Options can be :required, :optional and :allow-other-keys, and other initargs that are passed to MAKE-HASH-TABLE.
Examples:
(schema (hash-table (:x string :y number)))
(schema (hash-table (:x string :y number) :optional (:y)))
Schema for CONSes.
Syntax: (cons car-schema cdr-schema)
Examples:
(schema (cons symbol string))
Schemas disjunction.
Syntax: (or &rest schemas)
Example:
(schema (or string symbol))
Schemas conjunction.
Syntax: (and &rest schemas)
Example:
(schema (and integer (satisfies evenp)))
Defined schemas can be referenced via either ‘(schema schema-name)‘ or ‘(ref schema-name)‘ (they are identical).
Example:
SCHEMATA> (defschema person
(object person
((name string))))
#<OBJECT-SCHEMA {1006F8A813}>
SCHEMATA> (defparameter *list-of-person* (schema (list-of (ref person))))
*LIST-OF-PERSON*
SCHEMATA> *list-of-person*
#<LIST-SCHEMA {1006F8C2A3}>
SCHEMATA> (parse-with-schema *list-of-person* '((("name" . "Mariano")) (("name" . "Peter"))))
(((NAME . "Mariano")) ((NAME . "Peter")))
SCHEMATA> (validate-with-schema *list-of-person* '((("name" . 22)) (("name" . "Peter"))))
; processing (DEFMETHOD SCHEMA-VALIDATE ...); Evaluation aborted on #<SB-PCL::NO-APPLICABLE-METHOD-ERROR {1008018513}>.
SCHEMATA> (validate-with-schema *list-of-person* '((("name" . 22)) (("name" . "Peter"))))
; Evaluation aborted on #<SCHEMATA:VALIDATION-ERROR "~s is not of type: ~a" {10082EB883}>.
SCHEMATA> (validate-with-schema *list-of-person* '((("name" . "Mariano")) (("name" . "Peter"))))
NIL
SCHEMATA> (validate-with-schema *list-of-person* '((("names" . "Mariano")) (("name" . "Peter"))))
; Evaluation aborted on #<SCHEMATA:VALIDATION-ERROR "Attributes not part of schema: ~a" {1008CD3DD3}>.
Schemata integrates with the Lisp type system via the SATISFIES-SCHEMA type. Schemas can be thought as types over data. Defined schemas can be checked using TYPEP and CHECK-TYPE with the type ‘(satisfies-schema schema-name)‘.
Example:
SCHEMATA> (defschema string-schema string)
#<TYPE-SCHEMA STRING {10019DA8B3}>
SCHEMATA> (typep "foo" '(satisfies-schema string-schema))
T
SCHEMATA> (typep 22 '(satisfies-schema string-schema))
NIL
SCHEMATA> (let ((x "foo"))
(check-type x (satisfies-schema string-schema))
x)
"foo"
SCHEMA-CLASS classes get an schema attached.
Example:
SCHEMATA> (def-schema-class person ()
((name :type string :initarg :name)
(age :type integer :required nil :initarg :age)))
#<SCHEMA-CLASS SCHEMATA::PERSON>
SCHEMATA> (validate-with-schema (find-class 'person) '(("name" . "Mariano") ("age" . 22)))
NIL
SCHEMATA> (validate-with-schema (find-class 'person) '(("name" . "Mariano") ("age" . 'asdf)) :error-p nil)
#<VALIDATION-ERROR 'ASDF is not of type: INTEGER {100109F833}>
SCHEMATA> (generic-serializer:with-serializer :json
(generic-serializer:serialize (make-instance 'person :name "Mariano" :age 44)))
{"name":"Mariano","age":44}
Next: Reference, Previous: Schema types, Up: Top [Contents][Index]
Schemata can generate random data from schemas. It uses check-it library generators for that.
Load schemata-generators system.
Then call check-it:generate with a schema object.
Example:
(defschema person
(object person
((name string)
(age integer :required nil)
(friend (ref person) :required nil))))
(generate (find-schema 'person))
can generate:
((NAME . "21p7E0w8")
(FRIEND (NAME . "hD39Dwo")
(FRIEND (NAME . "QFC67xg206") (AGE . 4)
(FRIEND (NAME . "bRtUL1z51")
(FRIEND (NAME . "0")
(FRIEND (NAME . "ddB57idmh32C4T") (AGE . 1)
(FRIEND (NAME . "eNKzc") (AGE . 8))))))))
For more control over the generation, attach a generator to schemas via :generator initarg.
Next: Index, Previous: Data generation, Up: Top [Contents][Index]
| • SCHEMATA package |
Wrapper macro for schema definitions.
Register SCHEMA under NAME. The schema can then be accessed via FIND-SCHEMA.
Helper macro to define schema classes
Parses the string to an association list using the schema
Populate CLOS objects from data + schema. Attributes members of EXCLUDE parameter are not populated.
Generate a schema using the schema class meta info
Populate CLOS objects from data + schema. Only populates attributes available in DATA, validating them. Useful for PATCH rest api operations implementations. DATA should be an association list.
Find a schema definition by name
Validate input using schema. Useful for validating resource operations posted content (for :post and :put methods). Input can be a string or an association list.
Args: - schema (symbol or schema): The schema - data (alist): The data to validate. - format (keyword): The data format. - collect-errors (boolean): If true, collect all the validation errors. If false, return the first validation error found. Default: true. - error-p (boolean): If true, when validation errors are found, a validation error is signaled. If false, the validation errors are returned as the function result and no error is signaled.
Generate a schema from CLASS, using reflection.
Class precedence list: object-schema, schema, standard-object, t
Slots:
name — type: (or string symbol); initarg: :name; reader: schemata:object-name; writer: (setf schemata:object-name)
The name of the object.
attributes — type: list; initarg: :attributes; reader: schemata:object-attributes; writer: (setf schemata:object-attributes)
class — type: (or null symbol); initarg: :class; reader: schemata:object-class; writer: (setf schemata:object-class)
ignore-unknown-attributes — type: boolean; initarg: :ignore-unknown-attributes; reader: schemata::ignore-unknown-attributes; writer: (setf schemata::ignore-unknown-attributes)
serializer — type: (or null trivial-types:function-designator); initarg: :serializer; reader: schemata::object-serializer; writer: (setf schemata::object-serializer)
unserializer — type: (or null trivial-types:function-designator); initarg: :unserializer; reader: schemata::object-unserializer; writer: (setf schemata::object-unserializer)
Schema for CONSes.
Syntax: (cons car-schema cdr-schema)
Examples:
(schema (cons symbol string))
Class precedence list: cons-schema, schema, standard-object, t
Slots:
car-schema — type: t; initarg: :car-schema; reader: schemata::car-schema; writer: (setf schemata::car-schema)
The schema of CAR.
cdr-schema — type: t; initarg: :cdr-schema; reader: schemata::cdr-schema; writer: (setf schemata::cdr-schema)
The schema of CDR.
Schema for list with elements of certain type/schema.
Syntax: (list-of schema)
Examples:
(schema (list-of string)) (schema (list-of (or string number)))
Class precedence list: list-of-schema, schema, standard-object, t
Slots:
elements-schema — type: (not null); initarg: :elements-schema; reader: schemata::elements-schema; writer: (setf schemata::elements-schema)
Schema of the elements of the list
Schema for property lists with certain type of keys and values.
Syntax: (plist-of key-schema value-schema)
Examples:
(schema (plist-of keyword string))
Class precedence list: plist-of-schema, schema, standard-object, t
Slots:
key-schema — type: t; initarg: :key-schema; reader: schemata::key-schema; writer: (setf schemata::key-schema)
value-schema — type: t; initarg: :value-schema; reader: schemata::value-schema; writer: (setf schemata::value-schema)
Class precedence list: schema, standard-object, t
Slots:
documentation — type: (or null string); initarg: :documentation; reader: schemata:schema-documentation; writer: (setf schemata:schema-documentation)
generator — type: t; initarg: :generator; reader: schemata:schema-generator; writer: (setf schemata:schema-generator)
Schema for association lists with certain type of keys and values.
Syntax: (alist-of (key-schema . value-schema))
Examples:
(schema (alist-of (keyword . string)))
Class precedence list: alist-of-schema, schema, standard-object, t
Slots:
key-schema — type: t; initarg: :key-schema; reader: schemata::key-schema; writer: (setf schemata::key-schema)
value-schema — type: t; initarg: :value-schema; reader: schemata::value-schema; writer: (setf schemata::value-schema)
Schema for property lists with certain keys and values.
Syntax: (plist property-list &rest options)
where property-list specifies the schemas for the keys.
Options can be :required, :optional and :allow-other-keys.
Examples:
(schema (plist (:x string :y number))) (schema (plist (:x string :y number) :optional (:y)))
Class precedence list: plist-schema, schema, standard-object, t
Slots:
members — type: t; initarg: :members; reader: schemata::plist-members; writer: (setf schemata::plist-members)
required-keys — type: t; initarg: :required; reader: schemata::required-keys; writer: (setf schemata::required-keys)
optional-keys — type: t; initarg: :optional; reader: schemata::optional-keys; writer: (setf schemata::optional-keys)
allow-other-keys — type: t; initarg: :allow-other-keys; reader: schemata::allow-other-keys-p; writer: (setf schemata::allow-other-keys-p)
Schema for lists.
Syntax: (list &rest schemas)
Examples:
(schema (list string number)) (schema (list symbol number boolean))
Data matches when it is a list of the same size and the list schemas match. For instance, for the schema: (list symbol number symbol), ’(foo 33 bar) matches, but ’(foo 33) does not.
Class precedence list: list-schema, schema, standard-object, t
Slots:
schemas — type: t; initarg: :schemas; reader: schemata::list-schemas; writer: (setf schemata::list-schemas)
Class precedence list: schema-reference-schema, schema, standard-object, t
Slots:
name — type: symbol; initarg: :schema-name; reader: schemata::schema-name; writer: (setf schemata::schema-name)
Schema for association lists with certain keys and values.
Syntax: (alist association-list &rest options)
where association-list is a list of conses with key and schema.
Options can be :required, :optional and :allow-other-keys.
Examples:
(schema (alist ((:x . string)(:y . number)))) (schema (alist ((:x . string)(:y . number)) :optional (:y)))
Class precedence list: alist-schema, schema, standard-object, t
Slots:
members — type: t; initarg: :members; reader: schemata::alist-members; writer: (setf schemata::alist-members)
required-keys — type: (or boolean list); initarg: :required; reader: schemata::required-keys; writer: (setf schemata::required-keys)
If T (default), all keys are considered required. If a list, only those listed are considered required.
optional-keys — type: (or boolean list); initarg: :optional; reader: schemata::optional-keys; writer: (setf schemata::optional-keys)
If T, then all keys are considered optional. If a list, then the keys listed are considered optional.
allow-other-keys — type: t; initarg: :allow-other-keys; reader: schemata::allow-other-keys-p; writer: (setf schemata::allow-other-keys-p)
Whether other keys than the specified are allowed in the data being checked.
Metaclass for schema objects
Class precedence list: schema-class, standard-class, class, specializer, metaobject, standard-object, t
Slots:
schema-name — type: (or null string symbol); initarg: :schema-name; reader: schemata::schema-name; writer: (setf schemata::schema-name)
Class precedence list: schema-object, standard-object, t
Schema for a Common Lisp type.
Syntax: (schema type)
Examples:
(schema string) (schema integer)
Class precedence list: type-schema, schema, standard-object, t
Slots:
type — type: t; initarg: :type; reader: schemata:schema-type; writer: (setf schemata:schema-type)
Class precedence list: attribute-properties, standard-object, t
Slots:
required — type: boolean; initarg: :required; reader: schemata:attribute-required-p; writer: (setf schemata:attribute-required-p)
required-message — type: (or string null); initarg: :required-message; reader: schemata::attribute-required-message; writer: (setf schemata::attribute-required-message)
default — type: t; initarg: :default; reader: schemata::attribute-default; writer: (setf schemata::attribute-default)
validator — type: (or null trivial-types:function-designator); initarg: :validator; reader: schemata:attribute-validator; writer: (setf schemata:attribute-validator)
add-validator — type: (or null trivial-types:function-designator); initarg: :add-validator; reader: schemata:attribute-add-validator; writer: (setf schemata:attribute-add-validator)
parser — type: (or null trivial-types:function-designator); initarg: :parser; reader: schemata:attribute-parser; writer: (setf schemata:attribute-parser)
formatter — type: (or null trivial-types:function-designator); initarg: :formatter; reader: schemata:attribute-formatter; writer: (setf schemata:attribute-formatter)
external-name — type: (or string null); initarg: :external-name; reader: schemata:attribute-external-name; writer: (setf schemata:attribute-external-name)
serializer — type: t; initarg: :serializer; reader: schemata::attribute-serializer; writer: (setf schemata::attribute-serializer)
unserializer — type: (or null trivial-types:function-designator); initarg: :unserializer; reader: schemata::attribute-unserializer; writer: (setf schemata::attribute-unserializer)
Class precedence list: validation-error, error, serious-condition, condition, t
Class precedence list: attribute, schema, attribute-properties, standard-object, t
Slots:
name — type: symbol; initarg: :name; reader: schemata:attribute-name; writer: (setf schemata:attribute-name)
type — type: schemata:schema; initarg: :type; reader: schemata:attribute-type; writer: (setf schemata:attribute-type)
accessor — type: (or null symbol); initarg: :accessor; reader: schemata:attribute-accessor; writer: (setf schemata:attribute-accessor)
writer — type: (or null trivial-types:function-designator); initarg: :writer
reader — type: (or null trivial-types:function-designator); initarg: :reader
slot — type: (or null symbol); initarg: :slot; reader: schemata::attribute-slot; writer: (setf schemata::attribute-slot)
| Jump to: | S |
|---|
| Index Entry | Section | ||
|---|---|---|---|
| | |||
| S | |||
| schemata: | Top | ||
| | |||
| Jump to: | S |
|---|
| Jump to: | S |
|---|
| Jump to: | S |
|---|