|
@@ -10,45 +10,67 @@
|
|
|
# specific language governing permissions and limitations under the License.
|
|
|
from __future__ import annotations
|
|
|
|
|
|
+import typing as t
|
|
|
+from abc import ABC, abstractmethod
|
|
|
from datetime import date, datetime, time
|
|
|
from json import JSONEncoder
|
|
|
from pathlib import Path
|
|
|
-from types import FunctionType, LambdaType
|
|
|
|
|
|
from flask.json.provider import DefaultJSONProvider
|
|
|
|
|
|
from .._warnings import _warn
|
|
|
from ..icon import Icon
|
|
|
from ..utils import _date_to_string, _MapDict, _TaipyBase
|
|
|
+from ..utils.singleton import _Singleton
|
|
|
|
|
|
|
|
|
-def _default(o):
|
|
|
- if isinstance(o, Icon):
|
|
|
- return o._to_dict()
|
|
|
- if isinstance(o, _MapDict):
|
|
|
- return o._dict
|
|
|
- if isinstance(o, _TaipyBase):
|
|
|
- return o.get()
|
|
|
- if isinstance(o, (datetime, date, time)):
|
|
|
- return _date_to_string(o)
|
|
|
- if isinstance(o, Path):
|
|
|
- return str(o)
|
|
|
- if isinstance(o, FunctionType):
|
|
|
- return o.__name__
|
|
|
- if isinstance(o, LambdaType):
|
|
|
- return str(o)
|
|
|
- try:
|
|
|
- raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")
|
|
|
- except Exception as e:
|
|
|
- _warn("Exception in JSONEncoder", e)
|
|
|
+class JsonAdapter(ABC):
|
|
|
+ def register(self):
|
|
|
+ _TaipyJsonAdapter().register(self)
|
|
|
+
|
|
|
+ @abstractmethod
|
|
|
+ def parse(self, o) -> t.Union[t.Any, None]:
|
|
|
return None
|
|
|
|
|
|
|
|
|
+class _DefaultJsonAdapter(JsonAdapter):
|
|
|
+ def parse(self, o):
|
|
|
+ if isinstance(o, Icon):
|
|
|
+ return o._to_dict()
|
|
|
+ if isinstance(o, _MapDict):
|
|
|
+ return o._dict
|
|
|
+ if isinstance(o, _TaipyBase):
|
|
|
+ return o.get()
|
|
|
+ if isinstance(o, (datetime, date, time)):
|
|
|
+ return _date_to_string(o)
|
|
|
+ if isinstance(o, Path):
|
|
|
+ return str(o)
|
|
|
+
|
|
|
+
|
|
|
+class _TaipyJsonAdapter(object, metaclass=_Singleton):
|
|
|
+ def __init__(self):
|
|
|
+ self._adapters: t.List[JsonAdapter] = []
|
|
|
+ self.register(_DefaultJsonAdapter())
|
|
|
+
|
|
|
+ def register(self, adapter: JsonAdapter):
|
|
|
+ self._adapters.append(adapter)
|
|
|
+
|
|
|
+ def parse(self, o):
|
|
|
+ try:
|
|
|
+ for adapter in reversed(self._adapters):
|
|
|
+ if (output := adapter.parse(o)) is not None:
|
|
|
+ return output
|
|
|
+ raise TypeError(f"Object of type {type(o).__name__} is not JSON serializable")
|
|
|
+ except Exception as e:
|
|
|
+ _warn("Exception while resolving JSON", e)
|
|
|
+ return None
|
|
|
+
|
|
|
+
|
|
|
class _TaipyJsonEncoder(JSONEncoder):
|
|
|
def default(self, o):
|
|
|
- return _default(o)
|
|
|
+ return _TaipyJsonAdapter().parse(o)
|
|
|
|
|
|
|
|
|
class _TaipyJsonProvider(DefaultJSONProvider):
|
|
|
- default = staticmethod(_default) # type: ignore
|
|
|
+ default = staticmethod(_TaipyJsonAdapter().parse) # type: ignore
|
|
|
sort_keys = False
|