@@ -11,6 +11,8 @@ use smallvec::SmallVec;
1111
1212use  crate :: common:: missing_sentinel:: get_missing_sentinel_object; 
1313use  crate :: serializers:: extra:: SerCheck ; 
14+ use  crate :: serializers:: type_serializers:: any:: AnySerializer ; 
15+ use  crate :: serializers:: type_serializers:: function:: { FunctionPlainSerializer ,  FunctionWrapSerializer } ; 
1416use  crate :: PydanticSerializationUnexpectedValue ; 
1517
1618use  super :: computed_fields:: ComputedFields ; 
@@ -190,31 +192,26 @@ impl GeneralFieldsSerializer {
190192                ..extra
191193            } ; 
192194            if  let  Some ( ( next_include,  next_exclude) )  = self . filter . key_filter ( & key,  include,  exclude) ? { 
193-                 if  let  Some ( field)  = op_field { 
194-                     if  let  Some ( ref  serializer)  = field. serializer  { 
195-                         if  exclude_default ( & value,  & field_extra,  serializer) ? { 
196-                             continue ; 
197-                         } 
198-                         if  serialization_exclude_if ( field. serialization_exclude_if . as_ref ( ) ,  & value) ? { 
199-                             continue ; 
200-                         } 
201-                         let  value =
202-                             serializer. to_python ( & value,  next_include. as_ref ( ) ,  next_exclude. as_ref ( ) ,  & field_extra) ?; 
203-                         let  output_key = field. get_key_py ( output_dict. py ( ) ,  & field_extra) ; 
204-                         output_dict. set_item ( output_key,  value) ?; 
205-                     } 
195+                 let  ( key,  serializer)  = if  let  Some ( field)  = op_field { 
196+                     let  serializer = Self :: prepare_value ( & value,  field,  & field_extra) ?; 
206197
207198                    if  field. required  { 
208199                        used_req_fields += 1 ; 
209200                    } 
210-                 }  else  if  self . mode  == FieldsMode :: TypedDictAllow  { 
211-                     let  value = match  & self . extra_serializer  { 
212-                         Some ( serializer)  => { 
213-                             serializer. to_python ( & value,  next_include. as_ref ( ) ,  next_exclude. as_ref ( ) ,  & field_extra) ?
214-                         } 
215-                         _ => infer_to_python ( & value,  next_include. as_ref ( ) ,  next_exclude. as_ref ( ) ,  & field_extra) ?, 
201+ 
202+                     let  Some ( serializer)  = serializer else  { 
203+                         continue ; 
216204                    } ; 
217-                     output_dict. set_item ( key,  value) ?; 
205+ 
206+                     ( field. get_key_py ( output_dict. py ( ) ,  & field_extra) ,  serializer) 
207+                 }  else  if  self . mode  == FieldsMode :: TypedDictAllow  { 
208+                     let  serializer = self 
209+                         . extra_serializer 
210+                         . as_ref ( ) 
211+                         // If using `serialize_as_any`, extras are always inferred 
212+                         . filter ( |_| !extra. serialize_as_any ) 
213+                         . unwrap_or_else ( || AnySerializer :: get ( ) ) ; 
214+                     ( & key,  serializer) 
218215                }  else  if  field_extra. check  == SerCheck :: Strict  { 
219216                    return  Err ( PydanticSerializationUnexpectedValue :: new ( 
220217                        Some ( format ! ( "Unexpected field `{key}`" ) ) , 
@@ -223,7 +220,18 @@ impl GeneralFieldsSerializer {
223220                        None , 
224221                    ) 
225222                    . to_py_err ( ) ) ; 
226-                 } 
223+                 }  else  { 
224+                     continue ; 
225+                 } ; 
226+ 
227+                 // Use `no_infer` here because the `serialize_as_any` logic has been handled in `prepare_value` 
228+                 let  value = serializer. to_python_no_infer ( 
229+                     & value, 
230+                     next_include. as_ref ( ) , 
231+                     next_exclude. as_ref ( ) , 
232+                     & field_extra, 
233+                 ) ?; 
234+                 output_dict. set_item ( key,  value) ?; 
227235            } 
228236        } 
229237
@@ -257,7 +265,7 @@ impl GeneralFieldsSerializer {
257265        extra :  Extra , 
258266    )  -> Result < S :: SerializeMap ,  S :: Error >  { 
259267        // NOTE! As above, we maintain the order of the input dict assuming that's right 
260-         // we don't both with `used_fields ` here because on unions, `to_python(..., mode='json')` is used 
268+         // we don't both with `used_req_fields ` here because on unions, `to_python(..., mode='json')` is used 
261269        let  mut  map = serializer. serialize_map ( Some ( expected_len) ) ?; 
262270
263271        for  result in  main_iter { 
@@ -278,26 +286,23 @@ impl GeneralFieldsSerializer {
278286            let  filter = self . filter . key_filter ( & key,  include,  exclude) . map_err ( py_err_se_err) ?; 
279287            if  let  Some ( ( next_include,  next_exclude) )  = filter { 
280288                if  let  Some ( field)  = self . fields . get ( key_str)  { 
281-                     if  let  Some ( ref  serializer)  = field. serializer  { 
282-                         if  exclude_default ( & value,  & field_extra,  serializer) . map_err ( py_err_se_err) ? { 
283-                             continue ; 
284-                         } 
285-                         if  serialization_exclude_if ( field. serialization_exclude_if . as_ref ( ) ,  & value) 
286-                             . map_err ( py_err_se_err) ?
287-                         { 
288-                             continue ; 
289-                         } 
290-                         let  s = PydanticSerializer :: new ( 
291-                             & value, 
292-                             serializer, 
293-                             next_include. as_ref ( ) , 
294-                             next_exclude. as_ref ( ) , 
295-                             & field_extra, 
296-                         ) ; 
297-                         let  output_key = field. get_key_json ( key_str,  & field_extra) ; 
298-                         map. serialize_entry ( & output_key,  & s) ?; 
299-                     } 
289+                     let  Some ( serializer)  = Self :: prepare_value ( & value,  field,  & field_extra) . map_err ( py_err_se_err) ?
290+                     else  { 
291+                         continue ; 
292+                     } ; 
293+ 
294+                     // Use `no_infer` here because the `serialize_as_any` logic has been handled in `prepare_value` 
295+                     let  s = PydanticSerializer :: new_no_infer ( 
296+                         & value, 
297+                         serializer, 
298+                         next_include. as_ref ( ) , 
299+                         next_exclude. as_ref ( ) , 
300+                         & field_extra, 
301+                     ) ; 
302+                     let  output_key = field. get_key_json ( key_str,  & field_extra) ; 
303+                     map. serialize_entry ( & output_key,  & s) ?; 
300304                }  else  if  self . mode  == FieldsMode :: TypedDictAllow  { 
305+                     // FIXME: why is `extra_serializer` not used here when `serialize_as_any` is not set? 
301306                    let  output_key = infer_json_key ( & key,  & field_extra) . map_err ( py_err_se_err) ?; 
302307                    let  s = SerializeInfer :: new ( & value,  next_include. as_ref ( ) ,  next_exclude. as_ref ( ) ,  & field_extra) ; 
303308                    map. serialize_entry ( & output_key,  & s) ?; 
@@ -308,6 +313,49 @@ impl GeneralFieldsSerializer {
308313        Ok ( map) 
309314    } 
310315
316+     /// Gets the serializer to use for a field, applying `serialize_as_any` logic and applying any 
317+ /// field-level exclusions 
318+ fn  prepare_value < ' s > ( 
319+         value :  & Bound < ' _ ,  PyAny > , 
320+         field :  & ' s  SerField , 
321+         field_extra :  & Extra , 
322+     )  -> PyResult < Option < & ' s  Arc < CombinedSerializer > > >  { 
323+         let  Some ( serializer)  = field. serializer . as_ref ( )  else  { 
324+             // field excluded at schema level 
325+             return  Ok ( None ) ; 
326+         } ; 
327+ 
328+         if  exclude_default ( value,  field_extra,  serializer) ? { 
329+             return  Ok ( None ) ; 
330+         } 
331+ 
332+         // FIXME: should `exclude_if` be applied to extra fields too? 
333+         if  serialization_exclude_if ( field. serialization_exclude_if . as_ref ( ) ,  value) ? { 
334+             return  Ok ( None ) ; 
335+         } 
336+ 
337+         Ok ( Some ( 
338+             if  field_extra. serialize_as_any  &&
339+             // if serialize_as_any is set, we ensure that field serializers are 
340+             // still used, because this would match the `SerializeAsAny` annotation 
341+             // on a field 
342+             !matches ! ( 
343+                 serializer. as_ref( ) , 
344+                 CombinedSerializer :: Function ( FunctionPlainSerializer  { 
345+                     is_field_serializer:  true , 
346+                     ..
347+                 } )  | CombinedSerializer :: FunctionWrap ( FunctionWrapSerializer  { 
348+                     is_field_serializer:  true , 
349+                     ..
350+                 } ) 
351+             )  { 
352+                 AnySerializer :: get ( ) 
353+             }  else  { 
354+                 serializer
355+             } , 
356+         ) ) 
357+     } 
358+ 
311359    pub ( crate )  fn  add_computed_fields_python ( 
312360        & self , 
313361        model :  Option < & Bound < ' _ ,  PyAny > > , 
@@ -425,7 +473,7 @@ impl TypeSerializer for GeneralFieldsSerializer {
425473            _ => self . fields . len ( )  + option_length ! ( extra_dict)  + self . computed_field_count ( ) , 
426474        } ; 
427475        // NOTE! As above, we maintain the order of the input dict assuming that's right 
428-         // we don't both with `used_fields ` here because on unions, `to_python(..., mode='json')` is used 
476+         // we don't both with `used_req_fields ` here because on unions, `to_python(..., mode='json')` is used 
429477        let  mut  map = self . main_serde_serialize ( 
430478            dict_items ( & main_dict) , 
431479            expected_len, 
0 commit comments