diff --git a/booby/models.py b/booby/models.py index 89f4d63..8ac62b9 100644 --- a/booby/models.py +++ b/booby/models.py @@ -193,3 +193,46 @@ def to_json(self, *args, **kwargs): """ return json.dumps(dict(self), *args, **kwargs) + + @classmethod + def deserialize(self, raw): + result = {} + + for name, field in self._fields.items(): + raw_name = field.options.get('name') + + if raw_name is not None: + value = raw[raw_name] + else: + value = raw[name] + + if (isinstance(value, dict) and + isinstance(field, fields.Embedded)): + + value = field.model.deserialize(value) + + result[name] = value + + return result + + def serialize(self): + result = {} + + for name, field in self._fields.items(): + raw_name = field.options.get('name') + + value = getattr(self, name) + + if isinstance(value, Model): + value = value.serialize() + elif isinstance(value, list): + for i, item in enumerate(value): + if isinstance(item, Model): + value[i] = item.serialize() + + if raw_name is not None: + result[raw_name] = value + else: + result[name] = value + + return result diff --git a/tests/unit/test_models.py b/tests/unit/test_models.py index ef68382..7dac0ed 100644 --- a/tests/unit/test_models.py +++ b/tests/unit/test_models.py @@ -209,6 +209,82 @@ def setup(self): self.user = User(name='Jack', email='jack@example.com') +class TestDeserializeModel(object): + def test_should_return_dict_with_model_fields(self): + result = User.deserialize({ + 'name': 'Jack', 'email': 'jack@example.com'}) + + expect(result).to.have.keys(name='Jack', email='jack@example.com') + + def test_should_return_dict_with_model_mapped_fields(self): + result = UserWithMappedFields.deserialize({ + 'username': 'Jack', 'emailAddress': 'jack@example.com'}) + + expect(result).to.have.keys(name='Jack', email='jack@example.com') + + def test_should_deserialize_embedded_model_if_field_is_embedded_field(self): + result = UserWithTokenAndMappedFields.deserialize({ + 'name': 'Jack', 'email': 'jack@example.com', + 'token': { + 'accessToken':'foo', 'secretToken': 'bar' + } + }) + + expect(result['token']).to.have.keys(key='foo', secret='bar') + + +class TestSerializeModel(object): + def test_should_return_dict_with_model_fields(self): + user = User(name='Jack', email='jack@example.com') + + result = user.serialize() + + expect(result).to.have.keys(name='Jack', email='jack@example.com') + + def test_should_return_dict_with_model_mapped_fields(self): + user = UserWithMappedFields(name='Jack', email='jack@example.com') + + result = user.serialize() + + expect(result).to.have.keys(username='Jack', + emailAddress='jack@example.com') + + def test_should_serialize_embedded_model(self): + user = UserWithTokenAndMappedFields( + name='Jack', email='jack@example.com', + token={'key':'foo', 'secret': 'bar'}) + + result = user.serialize() + + expect(result['token']).to.have.keys(accessToken='foo', + secretToken='bar') + + def test_should_serialize_list_of_models(self): + user = UserWithList( + name='Jack', email='jack@example.com', + tokens=[self.token1, self.token2]) + + result = user.serialize() + + expect(result['tokens']).to.equal([self.token1.serialize(), + self.token2.serialize()]) + + def test_should_serialize_list_of_models_and_values(self): + user = UserWithList( + name='Jack', email='jack@example.com', + tokens=[self.token1, 'foo', self.token2]) + + result = user.serialize() + + expect(result['tokens']).to.equal([self.token1.serialize(), 'foo', + self.token2.serialize()]) + + def setup(self): + self.token1 = TokenWithMappedFields(key='foo', secret='bar') + self.token2 = TokenWithMappedFields(key='fuu', secret='baz') + + + class User(models.Model): name = fields.String() email = fields.String() @@ -242,3 +318,17 @@ class UserWithList(User): class Token(models.Model): key = fields.String() secret = fields.String() + + +class UserWithMappedFields(models.Model): + name = fields.String(name='username') + email = fields.String(name='emailAddress') + + +class TokenWithMappedFields(models.Model): + key = fields.String(name='accessToken') + secret = fields.String(name='secretToken') + + +class UserWithTokenAndMappedFields(User): + token = fields.Embedded(TokenWithMappedFields)