Skip to content

Commit 2efb8ae

Browse files
committed
refactor based on comments
1 parent 91e98f9 commit 2efb8ae

File tree

5 files changed

+321
-146
lines changed

5 files changed

+321
-146
lines changed

src/serializers/computed_fields.rs

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,29 @@ impl ComputedFields {
5252
// Do not serialize computed fields
5353
return Ok(());
5454
}
55-
for computed_field in &self.0 {
56-
let field_extra = Extra {
57-
field_name: Some(computed_field.property_name.as_str()),
58-
..*extra
59-
};
60-
computed_field.to_python(model, output_dict, filter, include, exclude, &field_extra)?;
55+
56+
if extra.sort_keys {
57+
let mut sorted_fields: Vec<&ComputedField> = self.0.iter().collect();
58+
sorted_fields.sort_by_cached_key(|field| match extra.serialize_by_alias_or(field.serialize_by_alias) {
59+
true => field.alias.as_str(),
60+
false => field.property_name.as_str(),
61+
});
62+
63+
for computed_field in sorted_fields {
64+
let field_extra = Extra {
65+
field_name: Some(computed_field.property_name.as_str()),
66+
..*extra
67+
};
68+
computed_field.to_python(model, output_dict, filter, include, exclude, &field_extra)?;
69+
}
70+
} else {
71+
for computed_field in &self.0 {
72+
let field_extra = Extra {
73+
field_name: Some(computed_field.property_name.as_str()),
74+
..*extra
75+
};
76+
computed_field.to_python(model, output_dict, filter, include, exclude, &field_extra)?;
77+
}
6178
}
6279
Ok(())
6380
}
@@ -76,33 +93,71 @@ impl ComputedFields {
7693
return Ok(());
7794
}
7895

79-
for computed_field in &self.0 {
80-
let property_name_py = computed_field.property_name_py.bind(model.py());
96+
if extra.sort_keys {
97+
let mut sorted_fields: Vec<&ComputedField> = self.0.iter().collect();
98+
sorted_fields.sort_by_cached_key(|field| match extra.serialize_by_alias_or(field.serialize_by_alias) {
99+
true => field.alias.as_str(),
100+
false => field.property_name.as_str(),
101+
});
102+
103+
for computed_field in sorted_fields {
104+
let property_name_py = computed_field.property_name_py.bind(model.py());
81105

82-
if let Some((next_include, next_exclude)) = filter
83-
.key_filter(property_name_py, include, exclude)
84-
.map_err(py_err_se_err)?
85-
{
86-
let value = model.getattr(property_name_py).map_err(py_err_se_err)?;
87-
if extra.exclude_none && value.is_none() {
88-
continue;
106+
if let Some((next_include, next_exclude)) = filter
107+
.key_filter(property_name_py, include, exclude)
108+
.map_err(py_err_se_err)?
109+
{
110+
let value = model.getattr(property_name_py).map_err(py_err_se_err)?;
111+
if extra.exclude_none && value.is_none() {
112+
continue;
113+
}
114+
let field_extra = Extra {
115+
field_name: Some(computed_field.property_name.as_str()),
116+
..*extra
117+
};
118+
let cfs = ComputedFieldSerializer {
119+
model,
120+
computed_field,
121+
include: next_include.as_ref(),
122+
exclude: next_exclude.as_ref(),
123+
extra: &field_extra,
124+
};
125+
let key = match extra.serialize_by_alias_or(computed_field.serialize_by_alias) {
126+
true => computed_field.alias.as_str(),
127+
false => computed_field.property_name.as_str(),
128+
};
129+
map.serialize_entry(key, &cfs)?;
130+
}
131+
}
132+
} else {
133+
for computed_field in &self.0 {
134+
let property_name_py = computed_field.property_name_py.bind(model.py());
135+
136+
if let Some((next_include, next_exclude)) = filter
137+
.key_filter(property_name_py, include, exclude)
138+
.map_err(py_err_se_err)?
139+
{
140+
let value = model.getattr(property_name_py).map_err(py_err_se_err)?;
141+
if extra.exclude_none && value.is_none() {
142+
continue;
143+
}
144+
let field_extra = Extra {
145+
field_name: Some(computed_field.property_name.as_str()),
146+
..*extra
147+
};
148+
let cfs = ComputedFieldSerializer {
149+
model,
150+
computed_field,
151+
include: next_include.as_ref(),
152+
exclude: next_exclude.as_ref(),
153+
extra: &field_extra,
154+
};
155+
let key = match extra.serialize_by_alias_or(computed_field.serialize_by_alias) {
156+
true => computed_field.alias.as_str(),
157+
false => computed_field.property_name.as_str(),
158+
};
159+
map.serialize_entry(key, &cfs)?;
89160
}
90-
let field_extra = Extra {
91-
field_name: Some(computed_field.property_name.as_str()),
92-
..*extra
93-
};
94-
let cfs = ComputedFieldSerializer {
95-
model,
96-
computed_field,
97-
include: next_include.as_ref(),
98-
exclude: next_exclude.as_ref(),
99-
extra: &field_extra,
100-
};
101-
let key = match extra.serialize_by_alias_or(computed_field.serialize_by_alias) {
102-
true => computed_field.alias.as_str(),
103-
false => computed_field.property_name.as_str(),
104-
};
105-
map.serialize_entry(key, &cfs)?;
106161
}
107162
}
108163
Ok(())

src/serializers/fields.rs

Lines changed: 16 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use super::filter::SchemaFilter;
1818
use super::infer::{infer_json_key, infer_serialize, infer_to_python, SerializeInfer};
1919
use super::shared::PydanticSerializer;
2020
use super::shared::{CombinedSerializer, TypeSerializer};
21-
use super::type_serializers::dict::sort_dict_recursive;
2221

2322
/// representation of a field for serialization
2423
#[derive(Debug)]
@@ -332,47 +331,23 @@ impl GeneralFieldsSerializer {
332331
if let Some(field) = self.fields.get(key_str) {
333332
if let Some(ref serializer) = field.serializer {
334333
if !exclude_default(value, &field_extra, serializer).map_err(py_err_se_err)? {
335-
// Get potentially sorted value
336-
if extra.sort_keys {
337-
let sorted_dict = sort_dict_recursive(value.py(), value).map_err(py_err_se_err)?;
338-
let s = PydanticSerializer::new(
339-
sorted_dict.as_ref(),
340-
serializer,
341-
next_include.as_ref(),
342-
next_exclude.as_ref(),
343-
&field_extra,
344-
);
345-
let output_key = field.get_key_json(key_str, &field_extra);
346-
map.serialize_entry(&output_key, &s)?;
347-
} else {
348-
let s = PydanticSerializer::new(
349-
value,
350-
serializer,
351-
next_include.as_ref(),
352-
next_exclude.as_ref(),
353-
&field_extra,
354-
);
355-
let output_key = field.get_key_json(key_str, &field_extra);
356-
map.serialize_entry(&output_key, &s)?;
357-
}
334+
// Let nested serializers handle their own sorting
335+
let s = PydanticSerializer::new(
336+
value,
337+
serializer,
338+
next_include.as_ref(),
339+
next_exclude.as_ref(),
340+
&field_extra,
341+
);
342+
let output_key = field.get_key_json(key_str, &field_extra);
343+
map.serialize_entry(&output_key, &s)?;
358344
}
359345
}
360346
} else if self.mode == FieldsMode::TypedDictAllow {
361347
let output_key = infer_json_key(key, &field_extra).map_err(py_err_se_err)?;
362-
// Get potentially sorted value
363-
if extra.sort_keys {
364-
let sorted_dict = sort_dict_recursive(value.py(), value).map_err(py_err_se_err)?;
365-
let s = SerializeInfer::new(
366-
sorted_dict.as_ref(),
367-
next_include.as_ref(),
368-
next_exclude.as_ref(),
369-
&field_extra,
370-
);
371-
map.serialize_entry(&output_key, &s)?;
372-
} else {
373-
let s = SerializeInfer::new(value, next_include.as_ref(), next_exclude.as_ref(), &field_extra);
374-
map.serialize_entry(&output_key, &s)?;
375-
}
348+
// Let nested serializers handle their own sorting
349+
let s = SerializeInfer::new(value, next_include.as_ref(), next_exclude.as_ref(), &field_extra);
350+
map.serialize_entry(&output_key, &s)?;
376351
}
377352
}
378353
Ok(())
@@ -541,19 +516,9 @@ impl TypeSerializer for GeneralFieldsSerializer {
541516
let filter = self.filter.key_filter(&key, include, exclude).map_err(py_err_se_err)?;
542517
if let Some((next_include, next_exclude)) = filter {
543518
let output_key = infer_json_key(&key, extra).map_err(py_err_se_err)?;
544-
if extra.sort_keys {
545-
let sorted_dict = sort_dict_recursive(value.py(), &value).map_err(py_err_se_err)?;
546-
let s = SerializeInfer::new(
547-
sorted_dict.as_ref(),
548-
next_include.as_ref(),
549-
next_exclude.as_ref(),
550-
extra,
551-
);
552-
map.serialize_entry(&output_key, &s)?;
553-
} else {
554-
let s = SerializeInfer::new(&value, next_include.as_ref(), next_exclude.as_ref(), extra);
555-
map.serialize_entry(&output_key, &s)?;
556-
}
519+
// Let nested serializers handle their own sorting
520+
let s = SerializeInfer::new(&value, next_include.as_ref(), next_exclude.as_ref(), extra);
521+
map.serialize_entry(&output_key, &s)?;
557522
}
558523
}
559524
}

src/serializers/infer.rs

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -710,13 +710,27 @@ fn serialize_pairs_python<'py>(
710710
let new_dict = PyDict::new(py);
711711
let filter = AnyFilter::new();
712712

713-
for result in pairs_iter {
714-
let (k, v) = result?;
715-
let op_next = filter.key_filter(&k, include, exclude)?;
716-
if let Some((next_include, next_exclude)) = op_next {
717-
let k = key_transform(k)?;
718-
let v = infer_to_python(&v, next_include.as_ref(), next_exclude.as_ref(), extra)?;
719-
new_dict.set_item(k, v)?;
713+
if extra.sort_keys {
714+
let mut pairs: Vec<(Bound<'py, PyAny>, Bound<'py, PyAny>)> = pairs_iter.collect::<PyResult<Vec<_>>>()?;
715+
pairs.sort_by_cached_key(|(k, _)| k.to_string());
716+
717+
for (k, v) in pairs {
718+
let op_next = filter.key_filter(&k, include, exclude)?;
719+
if let Some((next_include, next_exclude)) = op_next {
720+
let k = key_transform(k)?;
721+
let v = infer_to_python(&v, next_include.as_ref(), next_exclude.as_ref(), extra)?;
722+
new_dict.set_item(k, v)?;
723+
}
724+
}
725+
} else {
726+
for result in pairs_iter {
727+
let (k, v) = result?;
728+
let op_next = filter.key_filter(&k, include, exclude)?;
729+
if let Some((next_include, next_exclude)) = op_next {
730+
let k = key_transform(k)?;
731+
let v = infer_to_python(&v, next_include.as_ref(), next_exclude.as_ref(), extra)?;
732+
new_dict.set_item(k, v)?;
733+
}
720734
}
721735
}
722736
Ok(new_dict.into())
@@ -733,14 +747,29 @@ fn serialize_pairs_json<'py, S: Serializer>(
733747
let mut map = serializer.serialize_map(Some(iter_size))?;
734748
let filter = AnyFilter::new();
735749

736-
for result in pairs_iter {
737-
let (key, value) = result.map_err(py_err_se_err)?;
750+
if extra.sort_keys {
751+
let mut pairs: Vec<(Bound<'py, PyAny>, Bound<'py, PyAny>)> =
752+
pairs_iter.collect::<PyResult<Vec<_>>>().map_err(py_err_se_err)?;
753+
pairs.sort_by_cached_key(|(k, _)| k.to_string());
738754

739-
let op_next = filter.key_filter(&key, include, exclude).map_err(py_err_se_err)?;
740-
if let Some((next_include, next_exclude)) = op_next {
741-
let key = infer_json_key(&key, extra).map_err(py_err_se_err)?;
742-
let value_serializer = SerializeInfer::new(&value, next_include.as_ref(), next_exclude.as_ref(), extra);
743-
map.serialize_entry(&key, &value_serializer)?;
755+
for (key, value) in pairs {
756+
let op_next = filter.key_filter(&key, include, exclude).map_err(py_err_se_err)?;
757+
if let Some((next_include, next_exclude)) = op_next {
758+
let key = infer_json_key(&key, extra).map_err(py_err_se_err)?;
759+
let value_serializer = SerializeInfer::new(&value, next_include.as_ref(), next_exclude.as_ref(), extra);
760+
map.serialize_entry(&key, &value_serializer)?;
761+
}
762+
}
763+
} else {
764+
for result in pairs_iter {
765+
let (key, value) = result.map_err(py_err_se_err)?;
766+
767+
let op_next = filter.key_filter(&key, include, exclude).map_err(py_err_se_err)?;
768+
if let Some((next_include, next_exclude)) = op_next {
769+
let key = infer_json_key(&key, extra).map_err(py_err_se_err)?;
770+
let value_serializer = SerializeInfer::new(&value, next_include.as_ref(), next_exclude.as_ref(), extra);
771+
map.serialize_entry(&key, &value_serializer)?;
772+
}
744773
}
745774
}
746775
map.end()

0 commit comments

Comments
 (0)