# Native imports
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=None) -> 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('_')}
        if file:
            json.dump(attrs, file, ensure_ascii=False, indent=2)
        return json.dumps(attrs, 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)