diff --git a/batchata/core/job_result.py b/batchata/core/job_result.py
index eaeba3d..f4643b8 100644
--- a/batchata/core/job_result.py
+++ b/batchata/core/job_result.py
@@ -53,7 +53,7 @@ def to_dict(self) -> Dict[str, Any]:
if isinstance(self.parsed_response, dict):
parsed_response = self.parsed_response
elif isinstance(self.parsed_response, BaseModel):
- parsed_response = self.parsed_response.model_dump()
+ parsed_response = self.parsed_response.model_dump(mode='json')
else:
parsed_response = str(self.parsed_response)
diff --git a/docs/batchata.html b/docs/batchata.html
index 4703d6f..62991f0 100644
--- a/docs/batchata.html
+++ b/docs/batchata.html
@@ -3691,7 +3691,7 @@
Configuration
54 if isinstance(self.parsed_response, dict):
55 parsed_response = self.parsed_response
56 elif isinstance(self.parsed_response, BaseModel):
- 57 parsed_response = self.parsed_response.model_dump()
+ 57 parsed_response = self.parsed_response.model_dump(mode='json')
58 else:
59 parsed_response = str(self.parsed_response)
60
@@ -3979,7 +3979,7 @@ Configuration
54 if isinstance(self.parsed_response, dict):
55 parsed_response = self.parsed_response
56 elif isinstance(self.parsed_response, BaseModel):
-57 parsed_response = self.parsed_response.model_dump()
+57 parsed_response = self.parsed_response.model_dump(mode='json')
58 else:
59 parsed_response = str(self.parsed_response)
60
diff --git a/pyproject.toml b/pyproject.toml
index ef7ffbc..7974266 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "batchata"
-version = "0.4.5"
+version = "0.4.6"
description = "Unified Python API for AI batch requests with 50% cost savings on OpenAI and Anthropic"
readme = "README.md"
requires-python = ">=3.12"
diff --git a/tests/test_job_result_serialization.py b/tests/test_job_result_serialization.py
new file mode 100644
index 0000000..53078d6
--- /dev/null
+++ b/tests/test_job_result_serialization.py
@@ -0,0 +1,113 @@
+"""Test JobResult serialization with date fields."""
+
+import json
+from datetime import date
+from pydantic import BaseModel, Field
+
+from batchata.core.job_result import JobResult
+
+
+class MockPropertyData(BaseModel):
+ """Mock Pydantic model with date fields for testing."""
+ property_name: str = Field(..., description="Property name")
+ appraisal_date: date = Field(..., description="Date appraisal was performed")
+ last_sale_date: date | None = Field(None, description="Date of last sale")
+ appraised_value: float | None = Field(None, description="Appraised value")
+
+
+def test_job_result_serialization_with_dates():
+ """Test that JobResult can serialize Pydantic models with date fields to JSON."""
+ # Create a mock Pydantic model with date fields
+ property_data = MockPropertyData(
+ property_name="Test Property",
+ appraisal_date=date(2023, 10, 20),
+ last_sale_date=date(2022, 5, 15),
+ appraised_value=1500000.0
+ )
+
+ # Create JobResult with the mock data
+ job_result = JobResult(
+ job_id="test-job-123",
+ raw_response="Test raw response",
+ parsed_response=property_data,
+ input_tokens=100,
+ output_tokens=50,
+ cost_usd=0.15
+ )
+
+ # Test to_dict() method
+ result_dict = job_result.to_dict()
+
+ # Verify the parsed_response contains serialized dates as strings
+ assert result_dict["parsed_response"]["appraisal_date"] == "2023-10-20"
+ assert result_dict["parsed_response"]["last_sale_date"] == "2022-05-15"
+ assert result_dict["parsed_response"]["property_name"] == "Test Property"
+ assert result_dict["parsed_response"]["appraised_value"] == 1500000.0
+
+ # Test that the result can be serialized to JSON (this was failing before the fix)
+ json_str = json.dumps(result_dict, indent=2)
+
+ # Verify we can parse it back
+ parsed_back = json.loads(json_str)
+ assert parsed_back["parsed_response"]["appraisal_date"] == "2023-10-20"
+ assert parsed_back["parsed_response"]["last_sale_date"] == "2022-05-15"
+
+ # Test save_to_json method
+ import tempfile
+ import os
+
+ with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as tmp_file:
+ tmp_path = tmp_file.name
+
+ try:
+ # This should not raise an exception
+ job_result.save_to_json(tmp_path)
+
+ # Verify the file was created and contains valid JSON
+ with open(tmp_path, 'r') as f:
+ saved_data = json.load(f)
+
+ assert saved_data["parsed_response"]["appraisal_date"] == "2023-10-20"
+ assert saved_data["parsed_response"]["last_sale_date"] == "2022-05-15"
+
+ finally:
+ # Clean up
+ if os.path.exists(tmp_path):
+ os.unlink(tmp_path)
+
+
+def test_job_result_serialization_with_dict_response():
+ """Test that JobResult handles dict responses correctly (should not change)."""
+ # Test with dict response (no Pydantic model)
+ dict_response = {
+ "property_name": "Test Property",
+ "appraisal_date": "2023-10-20", # Already a string
+ "appraised_value": 1500000.0
+ }
+
+ job_result = JobResult(
+ job_id="test-job-dict",
+ raw_response="Test raw response",
+ parsed_response=dict_response,
+ input_tokens=100,
+ output_tokens=50,
+ cost_usd=0.15
+ )
+
+ # Test to_dict() method
+ result_dict = job_result.to_dict()
+
+ # Should be unchanged since it's already a dict
+ assert result_dict["parsed_response"]["appraisal_date"] == "2023-10-20"
+ assert result_dict["parsed_response"]["property_name"] == "Test Property"
+
+ # Should serialize to JSON without issues
+ json_str = json.dumps(result_dict, indent=2)
+ parsed_back = json.loads(json_str)
+ assert parsed_back["parsed_response"]["appraisal_date"] == "2023-10-20"
+
+
+if __name__ == "__main__":
+ test_job_result_serialization_with_dates()
+ test_job_result_serialization_with_dict_response()
+ print("All tests passed!")
\ No newline at end of file