diff --git a/pydantic_xml/serializers/serializer.py b/pydantic_xml/serializers/serializer.py index ec00561..e44f8b6 100644 --- a/pydantic_xml/serializers/serializer.py +++ b/pydantic_xml/serializers/serializer.py @@ -189,7 +189,11 @@ def preprocess_schema(cls, schema: pcs.CoreSchema, ctx: Context) -> Tuple[pcs.Co elif schema_type == 'nullable': ctx = ctx.replace(optional=True) - inner_schema = schema['schema'] + if schema_type == 'function-plain': + inner_schema = schema['serialization'] + else: + inner_schema = schema['schema'] + return cls.preprocess_schema(inner_schema, ctx) elif type_family is SchemaTypeFamily.JSON_OR_PYTHON: diff --git a/tests/test_preprocessors.py b/tests/test_preprocessors.py index 52ed990..1a0b2fd 100644 --- a/tests/test_preprocessors.py +++ b/tests/test_preprocessors.py @@ -1,3 +1,4 @@ +import datetime as dt from typing import Any, Dict, List import pydantic as pd @@ -105,3 +106,20 @@ def validate_model(self) -> 'TestModel': with pytest.raises(ValueError) as err: TestModel.from_xml(xml) assert err.value.errors()[0]['ctx']['orig'] == 'Value error, text' + + +def test_plain_validator(): + class TestModel(BaseXmlModel, tag='model1'): + element1: dt.date = element() + + @pd.field_validator('element1', mode='plain') + def validate_element1(cls, value: Any) -> Any: + return dt.datetime.strptime(value, '%Y%m%d').date() + + xml = '20260517' + model = TestModel.from_xml(xml) + assert model.element1 == dt.date(2026, 5, 17) + + with pytest.raises(ValueError) as err: + xml = 'aabb' + TestModel.from_xml(xml)