Description of the Bug
In backend/app/schemas.py, the DocumentResponse model has two fields that are stored as JSON strings in the database but are handled inconsistently:
keywords field — has a @field_validator that automatically parses the JSON string:
@field_validator("keywords", mode="before")
@classmethod
def parse_keywords(cls, v):
if isinstance(v, str):
return json.loads(v)
return v
extracted_urls field — has no field_validator:
extracted_urls: Optional[List[str]] = None
Instead, the route handler _deserialize_doc() in routes/documents.py manually parses extracted_urls:
if doc.extracted_urls:
doc_data["extracted_urls"] = json.loads(doc.extracted_urls)
This inconsistency means:
- Any code path that constructs
DocumentResponse without going through _deserialize_doc() will receive the raw JSON string instead of a parsed list
- If a new endpoint starts returning
DocumentResponse directly, extracted_urls will be broken
- The inconsistency is confusing and increases maintenance burden
Steps to Reproduce
- Upload a document that has extracted URLs
- Call an endpoint that returns
DocumentResponse but doesn't use _deserialize_doc()
- The
extracted_urls field contains a raw JSON string instead of a list
Expected Behavior
Both fields should be handled consistently. Add a @field_validator("extracted_urls", mode="before") to DocumentResponse similar to keywords.
Affected File
backend/app/schemas.py (lines ~135-146)
Suggested Fix
Add a field validator:
@field_validator("extracted_urls", mode="before")
@classmethod
def parse_extracted_urls(cls, v):
if isinstance(v, str):
return json.loads(v)
return v
Then remove the manual parsing from _deserialize_doc() in the route handler.
GSSoC '26
Description of the Bug
In
backend/app/schemas.py, theDocumentResponsemodel has two fields that are stored as JSON strings in the database but are handled inconsistently:keywordsfield — has a@field_validatorthat automatically parses the JSON string:extracted_urlsfield — has no field_validator:Instead, the route handler
_deserialize_doc()inroutes/documents.pymanually parsesextracted_urls:This inconsistency means:
DocumentResponsewithout going through_deserialize_doc()will receive the raw JSON string instead of a parsed listDocumentResponsedirectly,extracted_urlswill be brokenSteps to Reproduce
DocumentResponsebut doesn't use_deserialize_doc()extracted_urlsfield contains a raw JSON string instead of a listExpected Behavior
Both fields should be handled consistently. Add a
@field_validator("extracted_urls", mode="before")toDocumentResponsesimilar tokeywords.Affected File
backend/app/schemas.py(lines ~135-146)Suggested Fix
Add a field validator:
Then remove the manual parsing from
_deserialize_doc()in the route handler.GSSoC '26