Did you ever wonder what are alternatives for serializing and deserializing besides of simple json de/serializer ? I didn't but I've found this library that I find pretty neat :)

What Colander is all about ?

Well, to be honest I would not found this library if it was not for pyramid!

This library is a part of pyramid that integrates well into this pyramid ;D (yeah a bit to dry humour :D)

This library's main purpose is a type of serialization/deserialization mechanism with validation that can be extended.

How to use Colander?

You can use that i.e. within your small scripts / small frameworks that does not have a predefined serializers or where those serializers does not give you any type of extending for validating data.

In frameworks like django, you should find colander not much usefull, but in flask - I would take it - unless I'd find something more advanced at those frameworks.

So how to use it ? Let's have a look at small script that I've created for the sake of this:

import json

json_dict = {
    'height': 175,
    'surname': 'Somlesna',
    'id': 'None',
    'weight': 80,
    'name': 'Anselmos',
    'bmi': 26.12,
    'bmi_health_name': 'Overweight'
}
api_json_request_simulated = json.dumps(json_dict)

class JsonDeserialize:
    def __init__(self, **entry):
        self.__dict__.update(entry)

dict_deserialized = json.loads(api_json_request_simulated)
test1 = dict(dict_deserialized)
# no walidation at this point! in colander you have already a validation at this point! that would prevent having something that should not be given validated.

print JsonDeserialize(**test1)
print JsonDeserialize(**test1).bmi
print JsonDeserialize(**test1).bmi_health_name

This is a type of serialization to object that you could use. This ofcourse works. Main problem with it is that for making a validation you would need to replace mechanism for creating object from dict.

There are no way for json.loads/dumps to validate data (at least I don't know about).

But if someone from the blog audiance know about, please let me know :)

With colander you can validate your data before decoding it to dict:

import json
import logging
import pprint
import colander

json_dict = {
    'height': 175,
    'surname': 'Somlesna',
    'id': 'None',
    'weight': 80,
    'name': 'Anselmos',
    'bmi': 26.12,
    'bmi_health_name': 'Overweight'
}
api_json_request_simulated = json.dumps(json_dict)
dict_deserialized = json.loads(api_json_request_simulated)
test1 = dict(dict_deserialized)

class User(colander.MappingSchema):
    id = colander.SchemaNode(colander.Int())
    height = colander.SchemaNode(colander.Int(), validator=colander.Range(0,400))
    surname = colander.SchemaNode(colander.String())
    weight = colander.SchemaNode(colander.Int())
    name = colander.SchemaNode(colander.String())
    bmi = colander.SchemaNode(colander.Int())
    bmi_health_name = colander.SchemaNode(colander.String())

deserialized_obj = User().serialize(dict_deserialized)

This code will give you error! Why? because main int-validator for ID has triggered:

/local/lib/python2.7/site-packages/colander/__init__.py", line 704, in _impl
    raise error
    colander.Invalid: {'id': u'"None" is not a number'}

After a bit of changing now second validator will occur in this example:

import json
import logging
import pprint
import colander

json_dict = {
    'height': 402,
    'surname': 'Somlesna',
    'id': 1,
    'weight': 80,
    'name': 'Anselmos',
    'bmi': 26.12,
    'bmi_health_name': 'Overweight'
}
api_json_request_simulated = json.dumps(json_dict)
dict_deserialized = json.loads(api_json_request_simulated)
test1 = dict(dict_deserialized)

class User(colander.MappingSchema):
    id = colander.SchemaNode(colander.Int())
    height = colander.SchemaNode(colander.Int(), validator=colander.Range(0,400))
    surname = colander.SchemaNode(colander.String())
    weight = colander.SchemaNode(colander.Int())
    name = colander.SchemaNode(colander.String())
    bmi = colander.SchemaNode(colander.Int())
    bmi_health_name = colander.SchemaNode(colander.String())

deserialized_obj = User().deserialize(dict_deserialized)

Will output:

local/lib/python2.7/site-packages/colander/__init__.py", line 704, in _impl
    raise error
    colander.Invalid: {'height': u'402 is greater than maximum value 400'}

Colander schemas and types.

This rather small tutorial does not end on this. Colander has many schema-types and extensions that I want do share with you in next episode! So stay tuned!

Acknowledgements

Thanks!

That's it :) Comment, share or don't :)

If you have any suggestions what I should blog about in the next articles - please give me a hint :)

See you tomorrow! Cheers!



Comments

comments powered by Disqus