diff --git a/backend-compliance/compliance/services/company_profile_service.py b/backend-compliance/compliance/services/company_profile_service.py index 80059991..384f32aa 100644 --- a/backend-compliance/compliance/services/company_profile_service.py +++ b/backend-compliance/compliance/services/company_profile_service.py @@ -109,7 +109,12 @@ def _where_clause() -> str: def row_to_response(row: Any) -> CompanyProfileResponse: - """Convert a DB row to response model using zip-based column mapping.""" + """Convert a DB row to response model using zip-based column mapping. + + JSONB columns may arrive as JSON strings from raw text() queries — we + json.loads them first so the isinstance check below succeeds against the + expected Python type. + """ raw = dict(zip(_BASE_COLUMNS_LIST, row)) coerced: dict[str, Any] = {} @@ -117,6 +122,13 @@ def row_to_response(row: Any) -> CompanyProfileResponse: default, expected_type = _FIELD_DEFAULTS[col] value = raw[col] + # JSONB columns can come back as JSON-encoded strings from raw queries + if col in _JSONB_FIELDS and isinstance(value, str): + try: + value = json.loads(value) + except (json.JSONDecodeError, TypeError): + pass # fall through to default below + if expected_type == "STR": coerced[col] = str(value) elif expected_type == "STR_OR_NONE":