Created
December 6, 2017 20:52
-
-
Save CatarinaPBressan/4f6dc8b7826e352884f0561ac79d6898 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collections | |
from marshmallow.exceptions import ValidationError | |
from tracker.base import ma | |
# https://github.com/deckar01/marshmallow/commit/ | |
# b17786048dea2c380b9bb38f33802340f766e53a?diff=unified | |
class Dict(ma.Field): | |
"""A dict field. Supports dicts and dict-like objects. Composed by `Fields` | |
classes and instences for validation. | |
Example: :: | |
numbers = fields.Dict(fields.String(), fields.Float()) | |
:param Field key_field: A field class or instance used to validate keys. | |
:param Field value_field: A field class or instance used to validate | |
values. | |
:param kwargs: The same keyword arguments that :class:`Field` receives. | |
""" | |
default_error_messages = { | |
'invalid': 'Not a valid mapping type.' | |
} | |
def __init__(self, key_field, value_field, **kwargs): | |
super(Dict, self).__init__(**kwargs) | |
self.key_field = key_field | |
self.value_field = value_field | |
def _serialize(self, value, attr, obj): | |
if value is None: | |
return None | |
if not isinstance(value, collections.Mapping): | |
self.fail('invalid') | |
return dict([ | |
(idx, self.value_field._serialize(each, attr, obj)) | |
for idx, each in value.items() | |
]) | |
def _deserialize(self, value, attr, data): | |
if not isinstance(value, collections.Mapping): | |
self.fail('invalid') | |
result = {} | |
errors = {} | |
for key, value in value.items(): | |
try: | |
deserialized_key = self.key_field.deserialize(key) | |
except ValidationError as e: | |
result.update({key: e.messages}) | |
errors.update({key: e.messages}) | |
deserialized_key = key | |
try: | |
result.update({deserialized_key: | |
self.value_field.deserialize(value)}) | |
except ValidationError as e: | |
result.update({deserialized_key: e.messages}) | |
errors.update({deserialized_key: e.messages}) | |
if errors: | |
raise ValidationError(errors, data=result) | |
return result |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It looks like this would leave the original key (and value) in the result dict if the deserialization operation changes it. My strategy is effectively separating the keys and values into lists, deserializing them in place, then zipping them back into a dictionary. This should avoid leaving unprocessed data in the dict.