Skip to content

Commit 4c7fb60

Browse files
kesmit13claude
andcommitted
Add JSON wire format type conversions for UDF data types
Extend JSONEncoder.default() to handle datetime, date, timedelta, and Decimal types that were missing from the JSON format path. These types were added to the ROWDAT_1 binary format but the JSON encoder only handled bytes→base64. Without this, json.dumps() raises TypeError when a UDF returns any of these types via FORMAT JSON. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a22fc43 commit 4c7fb60

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

singlestoredb/functions/ext/json.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env python3
22
import base64
3+
import datetime
4+
import decimal
35
import json
46
from typing import Any
57
from typing import List
@@ -36,6 +38,22 @@ class JSONEncoder(json.JSONEncoder):
3638
def default(self, obj: Any) -> Any:
3739
if isinstance(obj, bytes):
3840
return base64.b64encode(obj).decode('utf-8')
41+
if isinstance(obj, datetime.datetime):
42+
return obj.strftime('%Y-%m-%d %H:%M:%S.%f')
43+
if isinstance(obj, datetime.date):
44+
return obj.isoformat()
45+
if isinstance(obj, datetime.timedelta):
46+
total_us = int(obj.total_seconds() * 1_000_000)
47+
sign = '-' if total_us < 0 else ''
48+
total_us = abs(total_us)
49+
us = total_us % 1_000_000
50+
total_secs = total_us // 1_000_000
51+
ss = total_secs % 60
52+
mm = (total_secs // 60) % 60
53+
hh = total_secs // 3600
54+
return f'{sign}{hh}:{mm:02d}:{ss:02d}.{us:06d}'
55+
if isinstance(obj, decimal.Decimal):
56+
return str(obj)
3957
return json.JSONEncoder.default(self, obj)
4058

4159

0 commit comments

Comments
 (0)