Manipulating Data Structures¶
Colander schemas have some utility functions which can be used to manipulate an appstruct or a cstruct. Nested data structures can be flattened into a single dictionary or a single flattened dictionary can be used to produce a nested data structure. Values of particular nodes can also be set or retrieved based on a flattened path spec.
Flattening a Data Structure¶
colander.SchemaNode.flatten()
can be used to convert a datastructure with
nested dictionaries and/or lists into a single flattened dictionary where each
key in the dictionary is a dotted name path to the node in the nested structure.
Consider the following schema:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | import colander class Friend(colander.TupleSchema): rank = colander.SchemaNode(colander.Int(), validator=colander.Range(0, 9999)) name = colander.SchemaNode(colander.String()) class Phone(colander.MappingSchema): location = colander.SchemaNode(colander.String(), validator=colander.OneOf(['home', 'work'])) number = colander.SchemaNode(colander.String()) class Friends(colander.SequenceSchema): friend = Friend() class Phones(colander.SequenceSchema): phone = Phone() class Person(colander.MappingSchema): name = colander.SchemaNode(colander.String()) age = colander.SchemaNode(colander.Int(), validator=colander.Range(0, 200)) friends = Friends() phones = Phones() |
Consider also a particular serialization of data using that schema:
1 2 3 4 5 6 7 | appstruct = { 'name':'keith', 'age':20, 'friends':[(1, 'jim'),(2, 'bob'), (3, 'joe'), (4, 'fred')], 'phones':[{'location':'home', 'number':'555-1212'}, {'location':'work', 'number':'555-8989'},], } |
This data can be flattened:
1 2 | schema = Person() fstruct = schema.flatten(appstruct) |
The resulting flattened structure would look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { 'name': 'keith', 'age': 20, 'friends.0.rank': 1, 'friends.0.name': 'jim', 'friends.1.rank': 2, 'friends.1.name': 'bob', 'friends.2.rank': 3, 'friends.2.name': 'joe', 'friends.3.rank': 4, 'friends.3.name': 'fred', 'phones.0.location': 'home', 'phones.0.number': '555-1212', 'phones.1.location': 'work', 'phones.1.number': '555-8989', } |
The process can be reversed using colander.SchemaNode.unflatten()
:
1 | appstruct = schema.unflatten(fstruct) |
Either an appstruct or a cstruct can be flattened or unflattened in this way.
Accessing and Mutating Nodes in a Data Structure¶
colander.SchemaNode.get_value
and colander.SchemaNode.set_value
can be used to access and mutate nodes in an appstruct or
cstruct. Using the example from above:
1 2 3 4 5 | # How much do I like Joe? rank = schema.get_value(appstruct, 'friends.2.rank') # Joe bought me beer. Let's promote Joe. schema.set_value(appstruct, 'friends.2.rank', rank + 5000) |