Permalink
Fetching contributors…
Cannot retrieve contributors at this time
220 lines (154 sloc) 6.86 KB

Extending Colander

You can extend Colander by defining a new :term:`type` or by defining a new :term:`validator`.

Defining a New Type

A type is a class that inherits from colander.SchemaType and implements these methods:

  • serialize: converts a Python data structure (:term:`appstruct`) into a serialization (:term:`cstruct`).
  • deserialize: converts a serialized value (:term:`cstruct`) into a Python data structure (:term:`appstruct`).
  • If it contains child nodes, it must also implement cstruct_children, flatten, unflatten, set_value and get_value methods. It may inherit from Mapping, Tuple, Set, List or Sequence to obtain these methods, but only if the expected behavior is the same.

Note

The cstruct_children method became required in Colander 0.9.9.

An Example

Here's a type which implements boolean serialization and deserialization. It serializes a boolean to the string "true" or "false" or the special :attr:`colander.null` sentinel; it then deserializes a string (presumably "true" or "false", but allows some wiggle room for "t", "on", "yes", "y", and "1") to a boolean value.

Here's how you would use the resulting class as part of a schema:

The above schema has a member named interested which will now be serialized and deserialized as a boolean, according to the logic defined in the Boolean type class.

Method Specifications

serialize

Arguments:

  • node: the SchemaNode associated with this type
  • appstruct: the :term:`appstruct` value that needs to be serialized

If appstruct is invalid, it should raise :exc:`colander.Invalid`, passing node as the first constructor argument.

It must deal specially with the value :attr:`colander.null`.

It must be able to make sense of any value generated by deserialize.

deserialize

Arguments:

  • node: the SchemaNode associated with this type
  • cstruct: the :term:`cstruct` value that needs to be deserialized

If cstruct is invalid, it should raise :exc:`colander.Invalid`, passing node as the first constructor argument.

It must deal specially with the value :attr:`colander.null`.

It must be able to make sense of any value generated by serialize.

cstruct_children

Arguments:

  • node: the SchemaNode associated with this type
  • cstruct: the :term:`cstruct` that the caller wants to obtain child values for

You only need to define this method for complex types that have child nodes, such as mappings and sequences.

cstruct_children should return a value based on cstruct for each child node in node (or an empty list if node has no children). If cstruct does not contain a value for a particular child, that child should be replaced with the colander.null value in the returned list.

cstruct_children should never raise an exception, even if it is passed a nonsensical cstruct argument. In that case, it should return a sequence of as many colander.null values as there are child nodes.

Constructor (__init__)

SchemaType does not define a constructor, and user code (not Colander) instantiates type objects, so custom types may define this method and use it for their own purposes.

Null Values

Both the serialize and deserialize methods must be able to receive :attr:`colander.null` values and handle them intelligently. This will happen whenever the data structure being serialized or deserialized does not provide a value for this node. In many cases, serialize or deserialize should just return :attr:`colander.null` when passed :attr:`colander.null`.

A type might also choose to return :attr:`colander.null` if the value it receives is logically (but not literally) null. For example, :class:`colander.String` type converts the empty string to colander.null within its deserialize method.

Defining a New Validator

A validator is a callable which accepts two positional arguments: node and value. It returns None if the value is valid. It raises a :class:`colander.Invalid` exception if the value is not valid. Here's a validator that checks if the value is a valid credit card number.

Here's how the resulting luhnok validator might be used in a schema:

Note that the validator doesn't need to check if the value is a string: this has already been done as the result of the type of the cc_number schema node being :class:`colander.String`. Validators are always passed the deserialized value when they are invoked.

The node value passed to the validator is a schema node object; it must in turn be passed to the :exc:`colander.Invalid` exception constructor if one needs to be raised.

For a more formal definition of a the interface of a validator, see :class:`colander.interfaces.Validator`.