fix(company-profile): deserialize JSONB columns in row_to_response
CI / detect-changes (push) Successful in 9s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / build-sha-integrity (push) Failing after 3s
CI / validate-canonical-controls (push) Successful in 13s
CI / loc-budget (push) Failing after 15s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 30s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / detect-changes (push) Successful in 9s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / build-sha-integrity (push) Failing after 3s
CI / validate-canonical-controls (push) Successful in 13s
CI / loc-budget (push) Failing after 15s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Has been skipped
CI / test-go (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-backend (push) Successful in 30s
CI / test-python-document-crawler (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
Raw text() queries return JSONB columns as JSON-encoded Python strings, not as Python list/dict objects. The existing isinstance check then fails and silently falls back to defaults — so list-valued fields like target_markets, offerings, processing_systems, ai_systems were always returned as their defaults regardless of stored content. Add a JSON-decode pass over _JSONB_FIELDS before the type check. Verified: PATCH of target_markets=["DE","EU"] now round-trips through GET correctly. Previously the DB had the right data but GET returned ["DE"] (the default). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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":
|
||||
|
||||
Reference in New Issue
Block a user