from datetime import date, datetime
from json import JSONEncoder
from uuid import UUID


class OPJSONEncoder(JSONEncoder):
  '''
  Adds support to the basic JSON format for additional types:
  - UUID
  - datetime.date
  - datetime.datetime (must be timezone-aware)

  Note: be aware that this is one-way serialization - if you serialize and deserialize an object with these properties,
  they will NOT have their original types in the deserialized object. In the context of an OPService, this isn't
  typically a problem, as we provide parsing functions specifically to convert these serialized strings back into their
  original data types (see 'type_validation_functions.py'):
  - uuid_str
  - iso_date
  - iso_datetime
  '''

  separators = (',', ':')

  def default(self, obj):
    if isinstance(obj, UUID):
      return str(obj)
    if isinstance(obj, date):
      return obj.isoformat()
    if isinstance(obj, datetime) and obj.tzinfo is not None:
      return obj.isoformat()
    try:
      return super().default(obj)
    except TypeError:
      raise
