Files
Wyvern-Castle/serializable.py
2026-01-23 09:47:06 +01:00

64 lines
2.7 KiB
Python

import json
from typing import Any, Dict, List, Type, TypeVar
T = TypeVar('T', bound='Serializable')
class Serializable:
@classmethod
def from_dict(cls: Type[T], data: Dict[str, Any]) -> T:
"""Creates an instance of the class from a dictionary."""
instance = cls.__new__(cls)
instance.deserialize_dict(data)
return instance
def serialize(self, file) -> str:
"""Serializes the object and all nested Serializable objects to JSON."""
def serialize_value(value: Any) -> Any:
if isinstance(value, Serializable):
return value.serialize_dict()
elif isinstance(value, list):
return [serialize_value(v) for v in value]
elif isinstance(value, dict):
return {k: serialize_value(v) for k, v in value.items()}
else:
return value
attrs = {k: serialize_value(v) for k, v in self.__dict__.items() if not k.startswith('_')}
return json.dumps(attrs, file, ensure_ascii=False, indent=2)
def serialize_dict(self) -> Dict[str, Any]:
"""Serializes the object to a dictionary (for nested serialization)."""
def serialize_value(value: Any) -> Any:
if isinstance(value, Serializable):
return value.serialize_dict()
elif isinstance(value, list):
return [serialize_value(v) for v in value]
elif isinstance(value, dict):
return {k: serialize_value(v) for k, v in value.items()}
else:
return value
return {k: serialize_value(v) for k, v in self.__dict__.items() if not k.startswith('_')}
def deserialize(self, json_str: str):
"""Deserializes JSON and recursively reconstructs Serializable objects."""
data = json.loads(json_str)
self.deserialize_dict(data)
def deserialize_dict(self, data: Dict[str, Any]):
"""Deserializes a dictionary and recursively reconstructs Serializable objects."""
for key, value in data.items():
if isinstance(value, dict) and 'py/class' in value:
# Handle nested Serializable objects
class_name = value['py/class']
class_ = globals()[class_name]
setattr(self, key, class_.from_dict(value))
elif isinstance(value, list):
# Handle lists of Serializable objects
setattr(self, key, [
item if not isinstance(item, dict) or 'py/class' not in item
else globals()[item['py/class']].from_dict(item)
for item in value
])
else:
setattr(self, key, value)