Skip to content

Commit

Permalink
Fix derived type serialization (#99)
Browse files Browse the repository at this point in the history
* Addresses #98
* fix derived type serialization

* deserialize into type derived from built-in type

* simpler subclass test

* fix builtin type check on typing hint error
  • Loading branch information
keotl committed Dec 22, 2019
1 parent 4c1e72c commit 760b6c1
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from typing import Type


from jivago.lang.annotations import Override
from jivago.lang.stream import Stream
from jivago.serialization.deserialization_strategy import DeserializationStrategy, T
from jivago.wsgi.invocation.incorrect_attribute_type_exception import IncorrectAttributeTypeException

BUILTIN_TYPES = (str, float, int)
BUILTIN_TYPES = (str, float, int, bool)


class BuiltInTypeDeserializationStrategy(DeserializationStrategy):

@Override
def can_handle_deserialization(self, declared_type: type) -> bool:
return declared_type in BUILTIN_TYPES
return type(declared_type) == type and issubclass(declared_type, BUILTIN_TYPES)

@Override
def deserialize(self, obj, declared_type: Type[T]) -> T:
Expand Down
9 changes: 5 additions & 4 deletions jivago/serialization/serializer.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
from typing import Union
from typing import Union, Iterable

from jivago.lang.stream import Stream
from jivago.serialization.serialization.datetime_serialization_strategy import DatetimeSerializationStrategy
from jivago.serialization.serialization_exception import SerializationException
from jivago.serialization.serialization_strategy import SerializationStrategy

BUILTIN_TYPES = (str, float, int, bool)


class Serializer(object):

def __init__(self):
self.strategies = [DatetimeSerializationStrategy()]
def __init__(self, additional_strategies: Iterable[SerializationStrategy] = ()):
self.strategies = [DatetimeSerializationStrategy(), *additional_strategies]

def serialize(self, obj: object) -> Union[dict, list]:
if obj is None:
Expand All @@ -24,7 +25,7 @@ def serialize(self, obj: object) -> Union[dict, list]:
for key, value in dictionary.items():
dictionary[key] = self.serialize(value)
return dictionary
if type(obj) in BUILTIN_TYPES:
if issubclass(type(obj), BUILTIN_TYPES):
return obj

if hasattr(obj, '__dict__'):
Expand Down
26 changes: 25 additions & 1 deletion test/serialization/test_dto_serialization_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,25 @@ def test_givenNoneAttribute_whenSerializing_thenSerializesToNoneOrNull(self):
def test_whenSerializing_DoesNotModifyTheSourceObject(self):
given = ACollectionDto([ChildDto()])

result = self.serialization_handler.serialize(given)
self.serialization_handler.serialize(given)

self.assertIsInstance(given.children[0], ChildDto)

def test_givenATypeDerivedFromABuiltinType_whenSerializing_thenSerializesAsBuiltinType(self):
given = {"name": DerivedString("my-derived-name")}

result = self.serialization_handler.serialize(given)

self.assertEqual("my-derived-name", result["name"])

def test_givenATypeDerivedFromABuiltingType_whenDeserializing_thenDeserializesAsBuiltinType(self):
given = {"name": "my-name"}

result: DtoWithDerivedStringMember = self.serialization_handler.deserialize(given, DtoWithDerivedStringMember)

self.assertEqual("my-name", result.name)
self.assertIsInstance(result.name, DerivedString)


@Serializable
class ADto(object):
Expand Down Expand Up @@ -246,6 +261,15 @@ class ANamedTuple(NamedTuple):
age: int


class DerivedString(str):
pass


@Serializable
class DtoWithDerivedStringMember(object):
name: DerivedString


A_NESTED_DTO = ANestedDto()
A_NESTED_DTO.child_dto = ChildDto()
A_NESTED_DTO.child_dto.name = "a name"

0 comments on commit 760b6c1

Please sign in to comment.