diff --git a/openapi_core/casting/schemas/casters.py b/openapi_core/casting/schemas/casters.py index 14794067..d1cd9e00 100644 --- a/openapi_core/casting/schemas/casters.py +++ b/openapi_core/casting/schemas/casters.py @@ -54,6 +54,10 @@ def items_caster(self) -> BaseSchemaCaster: return self.casters_factory.create(self.schema / "items") def cast(self, value: Any) -> List[Any]: + # str and bytes are not arrays according to the OpenAPI spec + if isinstance(value, (str, bytes)): + raise CastError(value, self.schema["type"]) + try: return list(map(self.items_caster, value)) except (ValueError, TypeError): diff --git a/openapi_core/casting/schemas/exceptions.py b/openapi_core/casting/schemas/exceptions.py index 0c4d25b1..242288d2 100644 --- a/openapi_core/casting/schemas/exceptions.py +++ b/openapi_core/casting/schemas/exceptions.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import Any from openapi_core.exceptions import OpenAPIError @@ -7,7 +8,7 @@ class CastError(OpenAPIError): """Schema cast operation error""" - value: str + value: Any type: str def __str__(self) -> str: diff --git a/tests/unit/casting/test_schema_casters.py b/tests/unit/casting/test_schema_casters.py index 64600bac..96cc522f 100644 --- a/tests/unit/casting/test_schema_casters.py +++ b/tests/unit/casting/test_schema_casters.py @@ -26,15 +26,17 @@ def test_array_invalid_type(self, caster_factory): with pytest.raises(CastError): caster_factory(schema)(value) - def test_array_invalid_value(self, caster_factory): + @pytest.mark.parametrize("value", [3.14, "foo", b"foo"]) + def test_array_invalid_value(self, value, caster_factory): spec = { "type": "array", "items": { - "type": "number", + "oneOf": [{"type": "number"}, {"type": "string"}], }, } schema = Spec.from_dict(spec) - value = 3.14 - with pytest.raises(CastError): + with pytest.raises( + CastError, match=f"Failed to cast value to array type: {value}" + ): caster_factory(schema)(value)