Source code for timApp.document.timjsonencoder
import datetime
import json
from dataclasses import is_dataclass, fields
from enum import Enum
from isodate import duration_isoformat
from isodate.duration import Duration
from jinja2 import Undefined
from sqlalchemy.ext.declarative import DeclarativeMeta
[docs]class TimJsonEncoder(json.JSONEncoder):
[docs] def default(self, o):
if isinstance(o, datetime.datetime):
if o.tzinfo is None:
o = o.replace(tzinfo=datetime.timezone.utc)
return o.isoformat()
if isinstance(o, (datetime.timedelta, Duration)):
return duration_isoformat(o)
if isinstance(o, Undefined):
return None
tojson = getattr(o, "to_json", None)
if tojson:
return tojson()
# from http://stackoverflow.com/a/31569287 with some changes
if isinstance(o.__class__, DeclarativeMeta):
data = {}
if hasattr(o, "__json__"):
flds = o.__json__()
else:
flds = dir(o)
flds = [
f
for f in flds
if not f.startswith("_")
and f not in ["metadata", "query", "query_class"]
]
for field in flds:
value = o.__getattribute__(field)
try:
json.dumps(value, cls=TimJsonEncoder)
data[field] = value
except TypeError:
data[field] = None
return data
if isinstance(o, Enum):
return o.value
if is_dataclass(o):
return {f.name: getattr(o, f.name) for f in fields(o)}
return None