# Path: src/apscheduler/abc.py
# class Serializer(metaclass=ABCMeta):
#     __slots__ = ()
# 
#     @abstractmethod
#     def serialize(self, obj) -> bytes:
#         pass
# 
#     def serialize_to_unicode(self, obj) -> str:
#         return b64encode(self.serialize(obj)).decode('ascii')
# 
#     @abstractmethod
#     def deserialize(self, serialized: bytes):
#         pass
# 
#     def deserialize_from_unicode(self, serialized: str):
#         return self.deserialize(b64decode(serialized))
# 
# Path: src/apscheduler/marshalling.py
# @overload
# def marshal_date(value: None) -> None:
#     ...
# 
# def marshal_object(obj) -> tuple[str, Any]:
#     return f'{obj.__class__.__module__}:{obj.__class__.__qualname__}', obj.__getstate__()
# 
# def unmarshal_object(ref: str, state):
#     cls = callable_from_ref(ref)
#     instance = cls.__new__(cls)
#     instance.__setstate__(state)
#     return instance


from datetime import datetime
from json import dumps, loads
from typing import Any
from ..abc import Serializer
from ..marshalling import marshal_date, marshal_object, unmarshal_object
import attrs
from __future__ import annotations





@attrs.define(kw_only=True, eq=False)
class JSONSerializer(Serializer):
    magic_key: str = '_apscheduler_json'
    dump_options: dict[str, Any] = attrs.field(factory=dict)
    load_options: dict[str, Any] = attrs.field(factory=dict)

    def __attrs_post_init__(self):
        self.dump_options['default'] = self._default_hook
        self.load_options['object_hook'] = self._object_hook

    def _default_hook(self, obj):
        if hasattr(obj, '__getstate__'):

# Path: src/apscheduler/abc.py
# class Serializer(metaclass=ABCMeta):
#     __slots__ = ()
# 
#     @abstractmethod
#     def serialize(self, obj) -> bytes:
#         pass
# 
#     def serialize_to_unicode(self, obj) -> str:
#         return b64encode(self.serialize(obj)).decode('ascii')
# 
#     @abstractmethod
#     def deserialize(self, serialized: bytes):
#         pass
# 
#     def deserialize_from_unicode(self, serialized: str):
#         return self.deserialize(b64decode(serialized))
# 
# Path: src/apscheduler/marshalling.py
# @overload
# def marshal_date(value: None) -> None:
#     ...
# 
# def marshal_object(obj) -> tuple[str, Any]:
#     return f'{obj.__class__.__module__}:{obj.__class__.__qualname__}', obj.__getstate__()
# 
# def unmarshal_object(ref: str, state):
#     cls = callable_from_ref(ref)
#     instance = cls.__new__(cls)
#     instance.__setstate__(state)
#     return instance


# Path: src/apscheduler/serializers/json.py
from datetime import datetime
from json import dumps, loads
from typing import Any
from ..abc import Serializer
from ..marshalling import marshal_date, marshal_object, unmarshal_object
import attrs

from __future__ import annotations





@attrs.define(kw_only=True, eq=False)
class JSONSerializer(Serializer):
    magic_key: str = '_apscheduler_json'
    dump_options: dict[str, Any] = attrs.field(factory=dict)
    load_options: dict[str, Any] = attrs.field(factory=dict)

    def __attrs_post_init__(self):
        self.dump_options['default'] = self._default_hook
        self.load_options['object_hook'] = self._object_hook

    def _default_hook(self, obj):
        if hasattr(obj, '__getstate__'):

            cls_ref, state = marshal_object(obj)