From 97defaf704c57495335f152e1adff4a25c988911 Mon Sep 17 00:00:00 2001 From: Lars Date: Sat, 28 Mar 2026 14:36:45 +0100 Subject: [PATCH] fix: serialize date objects to ISO format for JSON - Added serialize_dates() helper to convert date objects to strings - Applied to list_goals and get_goals_grouped endpoints - Fixes issue where start_date was saved but not visible in frontend - Python datetime.date objects need explicit .isoformat() conversion Root cause: FastAPI doesn't auto-serialize all date types consistently --- backend/routers/goals.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backend/routers/goals.py b/backend/routers/goals.py index aa87a27..43e40ef 100644 --- a/backend/routers/goals.py +++ b/backend/routers/goals.py @@ -25,6 +25,19 @@ from goal_utils import get_current_value_for_goal router = APIRouter(prefix="/api/goals", tags=["goals"]) + +def serialize_dates(obj): + """Convert date/datetime objects to ISO format strings for JSON serialization.""" + if obj is None: + return None + if isinstance(obj, dict): + return {k: serialize_dates(v) for k, v in obj.items()} + if isinstance(obj, list): + return [serialize_dates(item) for item in obj] + if isinstance(obj, (date,)): + return obj.isoformat() + return obj + # ============================================================================ # Pydantic Models # ============================================================================ @@ -362,6 +375,9 @@ def list_goals(session: dict = Depends(require_auth)): print(f"[ERROR] Failed to update progress for goal {goal.get('id')}: {e}") # Continue with other goals even if one fails + # Serialize date objects to ISO format strings + goals = serialize_dates(goals) + return goals except Exception as e: @@ -700,6 +716,9 @@ def get_goals_grouped(session: dict = Depends(require_auth)): goal_dict['focus_contributions'] = focus_map.get(goal['id'], []) grouped[cat].append(goal_dict) + # Serialize date objects to ISO format strings + grouped = serialize_dates(grouped) + return grouped # ============================================================================