Skip to content

Commit

Permalink
Changes in serialization API
Browse files Browse the repository at this point in the history
BaseDeserializer requires a class type to deserialize the raw_data
into a class. This creates a problem with Paylaod Deserialization,
where we have to deserialize the same payload multiple time.

BaseDeserializer, JSONDeserializer returns json and that get
converted into the class object after that. Payload Deserialization
will be app specific and will be implemented at project level.

Signed-off-by: Pradyumna Krishna <[email protected]>
  • Loading branch information
PradyumnaKrishna committed Sep 5, 2022
1 parent c011e6c commit 70074f5
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 32 deletions.
24 changes: 13 additions & 11 deletions securesystemslib/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ def default_deserializer() -> BaseDeserializer:
def default_serializer() -> BaseSerializer:
return JSONSerializer()

@classmethod
def from_bytes(
cls,
data: bytes,
deserializer: Optional[BaseDeserializer] = None
) -> "Envelope":

json = super().from_bytes(data, deserializer)
return cls.from_dict(json)

@classmethod
def from_dict(cls, data: dict) -> "Envelope":
"""Creates a DSSE Envelope from its JSON/dict representation.
Expand Down Expand Up @@ -172,18 +182,14 @@ def verify(self, keys: List[Key], threshold: int) -> Dict[str, Key]:

return accepted_keys

def deserialize_payload(
def get_payload(
self,
class_type: Any,
deserializer: Optional[BaseDeserializer] = None,
deserializer: BaseDeserializer,
) -> Any:
"""Parse DSSE payload.
Arguments:
class_type: The class to be deserialized. If the default
deserializer is used, it must implement ``JSONSerializable``.
deserializer: ``BaseDeserializer`` implementation to use.
Default is JSONDeserializer.
Raises:
DeserializationError: The payload cannot be deserialized.
Expand All @@ -192,8 +198,4 @@ def deserialize_payload(
The deserialized object of payload.
"""

if deserializer is None:
deserializer = JSONDeserializer()

payload = deserializer.deserialize(self.payload, class_type)
return payload
return deserializer.deserialize(self.payload)
28 changes: 7 additions & 21 deletions securesystemslib/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class BaseDeserializer(metaclass=abc.ABCMeta):
"""Abstract base class for deserialization of objects."""

@abc.abstractmethod
def deserialize(self, raw_data: bytes, cls: Any) -> Any:
def deserialize(self, raw_data: bytes) -> Any:
"""Deserialize bytes to a specific object."""

raise NotImplementedError # pragma: no cover
Expand All @@ -30,26 +30,22 @@ def deserialize(self, raw_data: bytes, cls: Any) -> Any:
class JSONDeserializer(BaseDeserializer):
"""Provides raw to JSON deserialize method."""

def deserialize(self, raw_data: bytes, cls: "JSONSerializable") -> Any:
"""Deserialize utf-8 encoded JSON bytes into an instance of cls.
def deserialize(self, raw_data: bytes) -> Any:
"""Deserialize utf-8 encoded JSON bytes into a dict.
Arguments:
raw_data: A utf-8 encoded bytes string.
cls: A "JSONSerializable" subclass.
Returns:
Object of the provided class type.
"""

try:
json_dict = json.loads(raw_data.decode("utf-8"))
obj = cls.from_dict(json_dict)
return json.loads(raw_data.decode("utf-8"))

except Exception as e:
raise DeserializationError("Failed to deserialize bytes") from e

return obj


class BaseSerializer(metaclass=abc.ABCMeta):
"""Abstract base class for serialization of objects."""
Expand Down Expand Up @@ -141,7 +137,7 @@ def from_bytes(
if deserializer is None:
deserializer = cls.default_deserializer()

return deserializer.deserialize(data, cls)
return deserializer.deserialize(data)

@classmethod
def from_file(
Expand Down Expand Up @@ -229,20 +225,10 @@ def to_file(

class JSONSerializable(metaclass=abc.ABCMeta):
"""Abstract base class that provide method to convert an instance of class
to dict and back to an object from its JSON/dict representation.
It provides `from_dict` and `to_dict` method, therefore, JSONSerializer and
JSONDeserializer requires a subclass of this class for serialization and
deserialization.
to dict. It provides `to_dict` method, therefore, JSONSerializer requires
a subclass of this class for serialization.
"""

@classmethod
@abc.abstractmethod
def from_dict(cls, data: dict) -> Any:
"""Creates an object from its JSON/dict representation."""

raise NotImplementedError # pragma: no cover

@abc.abstractmethod
def to_dict(self) -> dict:
"""Returns the JSON-serializable dictionary representation of self."""
Expand Down

0 comments on commit 70074f5

Please sign in to comment.