diff --git a/scrapegraphai/utils/schema_trasform.py b/scrapegraphai/utils/schema_trasform.py index 91f4c0332..cdc76d7ad 100644 --- a/scrapegraphai/utils/schema_trasform.py +++ b/scrapegraphai/utils/schema_trasform.py @@ -17,6 +17,11 @@ def transform_schema(pydantic_schema): def process_properties(properties): result = {} for key, value in properties.items(): + if "anyOf" in value: + # Optional[X] is emitted as anyOf [X, null]: describe it as X + variants = [v for v in value["anyOf"] if v.get("type") != "null"] + if len(variants) == 1: + value = {**value, **variants[0]} if "type" in value: if value["type"] == "array": if "items" in value and "$ref" in value["items"]: diff --git a/tests/utils/schema_transform_test.py b/tests/utils/schema_transform_test.py new file mode 100644 index 000000000..2dc7f9d7c --- /dev/null +++ b/tests/utils/schema_transform_test.py @@ -0,0 +1,27 @@ +from typing import List, Optional + +from pydantic import BaseModel, Field + +from scrapegraphai.utils.schema_trasform import transform_schema + + +class Seller(BaseModel): + name: str + + +class Product(BaseModel): + title: str = Field(description="Product title") + price: Optional[float] = Field(default=None, description="Price in USD") + tags: Optional[List[str]] = None + seller: Optional[Seller] = None + + +def test_transform_schema_keeps_optional_fields(): + result = transform_schema(Product.model_json_schema()) + + assert result == { + "title": {"type": "string", "description": "Product title"}, + "price": {"type": "number", "description": "Price in USD"}, + "tags": ["string"], + "seller": {"name": {"type": "string", "description": ""}}, + }