Skip to content

Commit c83a212

Browse files
committed
convert to string once and use it throughout
1 parent 567c669 commit c83a212

File tree

1 file changed

+36
-19
lines changed

1 file changed

+36
-19
lines changed

src/serializers/fields.rs

+36-19
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,28 @@ impl GeneralFieldsSerializer {
159159
if matches!(extra.sort_keys, SortKeysMode::Unsorted) {
160160
for result in main_iter {
161161
let (key, value) = result?;
162+
let key_str = key_str(&key)?;
162163
if let Some(is_required) =
163-
self.process_field_entry_python(&key, &value, &output_dict, include, exclude, &extra)?
164+
self.process_field_entry_python(key_str, &key, &value, &output_dict, include, exclude, &extra)?
164165
{
165166
if is_required {
166167
used_req_fields += 1;
167168
}
168169
}
169170
}
170171
} else {
171-
let mut items = main_iter.collect::<PyResult<Vec<_>>>()?;
172-
items.sort_by_cached_key(|(key, _)| key_str(key).unwrap_or_default().to_string());
173-
174-
for (key, value) in items {
172+
let mut items = main_iter
173+
.map(|r| -> PyResult<_> {
174+
let (k, v) = r?;
175+
let k_str = key_str(&k)?.to_owned();
176+
Ok((k_str, k, v))
177+
})
178+
.collect::<PyResult<Vec<_>>>()?;
179+
items.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
180+
181+
for (key_str, key, value) in items {
175182
if let Some(is_required) =
176-
self.process_field_entry_python(&key, &value, &output_dict, include, exclude, &extra)?
183+
self.process_field_entry_python(&key_str, &key, &value, &output_dict, include, exclude, &extra)?
177184
{
178185
if is_required {
179186
used_req_fields += 1;
@@ -218,8 +225,10 @@ impl GeneralFieldsSerializer {
218225
Ok(sorted_dict)
219226
}
220227

228+
#[allow(clippy::too_many_arguments)]
221229
fn process_field_entry_python<'py>(
222230
&self,
231+
key_str: &str,
223232
key: &Bound<'py, PyAny>,
224233
value: &Bound<'py, PyAny>,
225234
output_dict: &Bound<'py, PyDict>,
@@ -231,7 +240,6 @@ impl GeneralFieldsSerializer {
231240
// - Some(true) -> Field was required and processed
232241
// - Some(false) -> Field was processed but not required
233242
// - None -> Field was filtered out or skipped
234-
let key_str = key_str(key)?;
235243
let op_field = self.fields.get(key_str);
236244

237245
if extra.exclude_none && value.is_none() {
@@ -301,11 +309,11 @@ impl GeneralFieldsSerializer {
301309
None => infer_to_python(value, next_include.as_ref(), next_exclude.as_ref(), &field_extra)?,
302310
}
303311
};
304-
output_dict.set_item(key, processed_value)?;
312+
output_dict.set_item(key_str, processed_value)?;
305313
return Ok(None);
306314
} else if field_extra.check == SerCheck::Strict {
307315
return Err(PydanticSerializationUnexpectedValue::new(
308-
Some(format!("Unexpected field `{key}`")),
316+
Some(format!("Unexpected field `{key_str}`")),
309317
field_extra.model_type_name().map(|bound| bound.to_string()),
310318
None,
311319
)
@@ -332,20 +340,30 @@ impl GeneralFieldsSerializer {
332340
if matches!(extra.sort_keys, SortKeysMode::Unsorted) {
333341
for result in main_iter {
334342
let (key, value) = result.map_err(py_err_se_err)?;
335-
self.process_field_entry::<S>(&key, &value, &mut map, include, exclude, &extra)?;
343+
let key_str = key_str(&key).map_err(py_err_se_err)?;
344+
self.process_field_entry::<S>(key_str, &key, &value, &mut map, include, exclude, &extra)?;
336345
}
337346
} else {
338-
let mut items = main_iter.collect::<PyResult<Vec<_>>>().map_err(py_err_se_err)?;
339-
items.sort_by_cached_key(|(key, _)| key_str(key).unwrap_or_default().to_string());
340-
for (key, value) in items {
341-
self.process_field_entry::<S>(&key, &value, &mut map, include, exclude, &extra)?;
347+
let mut items = main_iter
348+
.map(|r| -> PyResult<_> {
349+
let (k, v) = r?;
350+
let k_str = key_str(&k)?.to_owned();
351+
Ok((k_str, k, v))
352+
})
353+
.collect::<PyResult<Vec<_>>>()
354+
.map_err(py_err_se_err)?;
355+
items.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
356+
for (key_str, key, value) in items {
357+
self.process_field_entry::<S>(&key_str, &key, &value, &mut map, include, exclude, &extra)?;
342358
}
343359
}
344360
Ok(map)
345361
}
346362

363+
#[allow(clippy::too_many_arguments)]
347364
fn process_field_entry<'py, S: serde::ser::Serializer>(
348365
&self,
366+
key_str: &str,
349367
key: &Bound<'py, PyAny>,
350368
value: &Bound<'py, PyAny>,
351369
map: &mut S::SerializeMap,
@@ -356,15 +374,14 @@ impl GeneralFieldsSerializer {
356374
if extra.exclude_none && value.is_none() {
357375
return Ok(());
358376
}
359-
let field_key_str = key_str(key).map_err(py_err_se_err)?;
360377
let field_extra = Extra {
361-
field_name: Some(field_key_str),
378+
field_name: Some(key_str),
362379
..*extra
363380
};
364381

365382
let filter = self.filter.key_filter(key, include, exclude).map_err(py_err_se_err)?;
366383
if let Some((next_include, next_exclude)) = filter {
367-
if let Some(field) = self.fields.get(field_key_str) {
384+
if let Some(field) = self.fields.get(key_str) {
368385
if let Some(ref serializer) = field.serializer {
369386
if !exclude_default(value, &field_extra, serializer).map_err(py_err_se_err)? {
370387
if matches!(extra.sort_keys, SortKeysMode::Recursive) && value.downcast::<PyDict>().is_ok() {
@@ -376,7 +393,7 @@ impl GeneralFieldsSerializer {
376393
next_exclude.as_ref(),
377394
&field_extra,
378395
);
379-
let output_key = field.get_key_json(field_key_str, &field_extra);
396+
let output_key = field.get_key_json(key_str, &field_extra);
380397
map.serialize_entry(&output_key, &s)?;
381398
} else {
382399
let s = PydanticSerializer::new(
@@ -386,7 +403,7 @@ impl GeneralFieldsSerializer {
386403
next_exclude.as_ref(),
387404
&field_extra,
388405
);
389-
let output_key = field.get_key_json(field_key_str, &field_extra);
406+
let output_key = field.get_key_json(key_str, &field_extra);
390407
map.serialize_entry(&output_key, &s)?;
391408
}
392409
}

0 commit comments

Comments
 (0)