2626 'computed_element' ,
2727 'xml_field_serializer' ,
2828 'xml_field_validator' ,
29+ 'XmlFieldSerializer' ,
30+ 'XmlFieldValidator' ,
2931 'BaseXmlModel' ,
3032 'RootXmlModel' ,
3133)
@@ -355,6 +357,16 @@ def wrapper(func: SerializerFuncT) -> SerializerFuncT:
355357 return wrapper
356358
357359
360+ @dc .dataclass (frozen = True )
361+ class XmlFieldValidator :
362+ func : ValidatorFunc
363+
364+
365+ @dc .dataclass (frozen = True )
366+ class XmlFieldSerializer :
367+ func : SerializerFunc
368+
369+
358370@te .dataclass_transform (kw_only_default = True , field_specifiers = (attr , element , wrapped , pd .Field ))
359371class XmlModelMeta (ModelMetaclass ):
360372 """
@@ -374,8 +386,32 @@ def __new__(
374386 if not is_abstract :
375387 cls .__build_serializer__ ()
376388
389+ cls ._collect_xml_field_serializers_validators (cls )
390+
377391 return cls
378392
393+ @classmethod
394+ def _collect_xml_field_serializers_validators (mcls , cls : Type ['BaseXmlModel' ]) -> None :
395+ for field_name , field_info in cls .model_fields .items ():
396+ for metadatum in field_info .metadata :
397+ if isinstance (metadatum , XmlFieldValidator ):
398+ cls .__xml_field_validators__ [field_name ] = metadatum .func
399+ if isinstance (metadatum , XmlFieldSerializer ):
400+ cls .__xml_field_serializers__ [field_name ] = metadatum .func
401+
402+ # find custom validators/serializers in all defined attributes
403+ # though we want to skip any BaseModel attributes, as these can never be field
404+ # serializers/validators, and getting certain pydantic fields
405+ # may cause recursion errors for recursive / self-referential models
406+ for attr_name in set (dir (cls )) - set (dir (BaseModel )):
407+ if func := getattr (cls , attr_name , None ):
408+ if fields := getattr (func , '__xml_field_serializer__' , None ):
409+ for field in fields :
410+ cls .__xml_field_serializers__ [field ] = func
411+ if fields := getattr (func , '__xml_field_validator__' , None ):
412+ for field in fields :
413+ cls .__xml_field_validators__ [field ] = func
414+
379415
380416ModelT = TypeVar ('ModelT' , bound = 'BaseXmlModel' )
381417
@@ -435,19 +471,6 @@ def __init_subclass__(
435471 cls .__xml_field_serializers__ = {}
436472 cls .__xml_field_validators__ = {}
437473
438- # find custom validators/serializers in all defined attributes
439- # though we want to skip any Base(Xml)Model attributes, as these can never be field
440- # serializers/validators, and getting certain pydantic fields, like __pydantic_post_init__
441- # may cause recursion errors for recursive / self-referential models
442- for attr_name in set (dir (cls )) - set (dir (BaseXmlModel )):
443- if func := getattr (cls , attr_name , None ):
444- if fields := getattr (func , '__xml_field_serializer__' , None ):
445- for field in fields :
446- cls .__xml_field_serializers__ [field ] = func
447- if fields := getattr (func , '__xml_field_validator__' , None ):
448- for field in fields :
449- cls .__xml_field_validators__ [field ] = func
450-
451474 @classmethod
452475 def __build_serializer__ (cls ) -> None :
453476 if cls is BaseXmlModel :
0 commit comments