@@ -9,7 +9,7 @@ use crate::build_tools::py_schema_err;
99use  crate :: common:: union:: { Discriminator ,  SMALL_UNION_THRESHOLD } ; 
1010use  crate :: definitions:: DefinitionsBuilder ; 
1111use  crate :: serializers:: PydanticSerializationUnexpectedValue ; 
12- use  crate :: tools:: { truncate_safe_repr ,   SchemaDict } ; 
12+ use  crate :: tools:: SchemaDict ; 
1313
1414use  super :: { 
1515    infer_json_key,  infer_serialize,  infer_to_python,  BuildSerializer ,  CombinedSerializer ,  Extra ,  SerCheck , 
@@ -78,6 +78,7 @@ fn union_serialize<S>(
7878    extra :  & Extra , 
7979    choices :  & [ CombinedSerializer ] , 
8080    retry_with_lax_check :  bool , 
81+     py :  Python < ' _ > , 
8182)  -> PyResult < Option < S > >  { 
8283    // try the serializers in left to right order with error_on fallback=true 
8384    let  mut  new_extra = extra. clone ( ) ; 
@@ -104,14 +105,23 @@ fn union_serialize<S>(
104105    // If extra.check is SerCheck::None, we're in a top-level union. We should thus raise the warnings 
105106    if  extra. check  == SerCheck :: None  { 
106107        for  err in  & errors { 
107-             extra. warnings . custom_warning ( err. to_string ( ) ) ; 
108+             if  err. is_instance_of :: < PydanticSerializationUnexpectedValue > ( py)  { 
109+                 let  pydantic_err:  PydanticSerializationUnexpectedValue  = err. value ( py) . extract ( ) ?; 
110+                 extra. warnings . register_warning ( pydantic_err) ; 
111+             }  else  { 
112+                 extra
113+                     . warnings 
114+                     . register_warning ( PydanticSerializationUnexpectedValue :: new_from_msg ( Some ( 
115+                         err. to_string ( ) , 
116+                     ) ) ) ; 
117+             } 
108118        } 
109119    } 
110120    // Otherwise, if we've encountered errors, return them to the parent union, which should take 
111121    // care of the formatting for us 
112122    else  if  !errors. is_empty ( )  { 
113123        let  message = errors. iter ( ) . map ( ToString :: to_string) . collect :: < Vec < _ > > ( ) . join ( "\n " ) ; 
114-         return  Err ( PydanticSerializationUnexpectedValue :: new_from_msg ( Some ( message) ) ) ; 
124+         return  Err ( PydanticSerializationUnexpectedValue :: new_from_msg ( Some ( message) ) . to_py_err ( ) ) ; 
115125    } 
116126
117127    Ok ( None ) 
@@ -130,6 +140,7 @@ impl TypeSerializer for UnionSerializer {
130140            extra, 
131141            & self . choices , 
132142            self . retry_with_lax_check ( ) , 
143+             value. py ( ) , 
133144        ) ?
134145        . map_or_else ( || infer_to_python ( value,  include,  exclude,  extra) ,  Ok ) 
135146    } 
@@ -140,6 +151,7 @@ impl TypeSerializer for UnionSerializer {
140151            extra, 
141152            & self . choices , 
142153            self . retry_with_lax_check ( ) , 
154+             key. py ( ) , 
143155        ) ?
144156        . map_or_else ( || infer_json_key ( key,  extra) ,  Ok ) 
145157    } 
@@ -157,6 +169,7 @@ impl TypeSerializer for UnionSerializer {
157169            extra, 
158170            & self . choices , 
159171            self . retry_with_lax_check ( ) , 
172+             value. py ( ) , 
160173        )  { 
161174            Ok ( Some ( v) )  => infer_serialize ( v. bind ( value. py ( ) ) ,  serializer,  None ,  None ,  extra) , 
162175            Ok ( None )  => infer_serialize ( value,  serializer,  include,  exclude,  extra) , 
@@ -328,17 +341,18 @@ impl TaggedUnionSerializer {
328341        }  else  if  extra. check  == SerCheck :: None  { 
329342            // If extra.check is SerCheck::None, we're in a top-level union. We should thus raise 
330343            // this warning 
331-             let  value_str = truncate_safe_repr ( value,  None ) ; 
332-             extra. warnings . custom_warning ( 
333-                 format ! ( 
334-                     "Failed to get discriminator value for tagged union serialization with value `{value_str}` - defaulting to left to right union serialization." 
344+             extra. warnings . register_warning ( 
345+                 PydanticSerializationUnexpectedValue :: new ( 
346+                     Some ( "Defaulting to left to right union serialization - failed to get discriminator value for tagged union serialization" . to_string ( ) ) , 
347+                     None , 
348+                     Some ( value. clone ( ) . unbind ( ) ) , 
335349                ) 
336350            ) ; 
337351        } 
338352
339353        // if we haven't returned at this point, we should fallback to the union serializer 
340354        // which preserves the historical expectation that we do our best with serialization 
341355        // even if that means we resort to inference 
342-         union_serialize ( selector,  extra,  & self . choices ,  self . retry_with_lax_check ( ) ) 
356+         union_serialize ( selector,  extra,  & self . choices ,  self . retry_with_lax_check ( ) ,  value . py ( ) ) 
343357    } 
344358} 
0 commit comments