diff --git a/singer_sdk/_singerlib/messages.py b/singer_sdk/_singerlib/messages.py index 02c0f30f2..016e0b8b9 100644 --- a/singer_sdk/_singerlib/messages.py +++ b/singer_sdk/_singerlib/messages.py @@ -6,14 +6,11 @@ import sys import typing as t from dataclasses import asdict, dataclass, field -from datetime import timezone +from datetime import datetime, timezone import simplejson as json from dateutil.parser import parse -if t.TYPE_CHECKING: - from datetime import datetime - class SingerMessageType(str, enum.Enum): """Singer specification message types.""" @@ -25,6 +22,18 @@ class SingerMessageType(str, enum.Enum): BATCH = "BATCH" +def _default_encoding(obj: t.Any) -> str: # noqa: ANN401 + """Default JSON encoder. + + Args: + obj: The object to encode. + + Returns: + The encoded object. + """ + return obj.isoformat(sep="T") if isinstance(obj, datetime) else str(obj) + + def exclude_null_dict(pairs: list[tuple[str, t.Any]]) -> dict[str, t.Any]: """Exclude null values from a dictionary. @@ -211,7 +220,7 @@ def format_message(message: Message) -> str: Returns: The formatted message. """ - return json.dumps(message.to_dict(), use_decimal=True, default=str) + return json.dumps(message.to_dict(), use_decimal=True, default=_default_encoding) def write_message(message: Message) -> None: diff --git a/singer_sdk/helpers/_typing.py b/singer_sdk/helpers/_typing.py index 81ffcc333..8b937d973 100644 --- a/singer_sdk/helpers/_typing.py +++ b/singer_sdk/helpers/_typing.py @@ -45,7 +45,7 @@ def to_json_compatible(val: t.Any) -> t.Any: # noqa: ANN401 If given a naive datetime object, pendulum automatically makes it utc """ if isinstance(val, (datetime.datetime, pendulum.DateTime)): - return pendulum.instance(val).isoformat() + return pendulum.instance(val).isoformat("T") return val