Skip to content

Commit

Permalink
Merge pull request #1199 from dtolnay/sort
Browse files Browse the repository at this point in the history
Add methods on Map and Value to destroy preserved ordering
  • Loading branch information
dtolnay authored Oct 17, 2024
2 parents faab2e8 + c1a06c1 commit 2679e30
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,28 @@ impl Map<String, Value> {
{
self.map.retain(f);
}

/// Sorts this map's entries in-place using `str`'s usual ordering.
///
/// If serde_json's "preserve_order" feature is not enabled, this method
/// does no work because all JSON maps are always kept in a sorted state.
///
/// If serde_json's "preserve_order" feature is enabled, this method
/// destroys the original source order or insertion order of this map in
/// favor of an alphanumerical order that matches how a BTreeMap with the
/// same contents would be ordered. This takes **O(n log n + c)** time where
/// _n_ is the length of the map and _c_ is the capacity.
///
/// Other maps nested within the values of this map are not sorted. If you
/// need the entire data structure to be sorted at all levels, you must also
/// call `map.`[`values_mut`]`().for_each(`[`Value::sort_all_objects`]`)`.
///
/// [`values_mut`]: Map::values_mut
#[inline]
pub fn sort_keys(&mut self) {
#[cfg(feature = "preserve_order")]
self.map.sort_unstable_keys();
}
}

#[allow(clippy::derivable_impls)] // clippy bug: https://github.com/rust-lang/rust-clippy/issues/7655
Expand Down
26 changes: 26 additions & 0 deletions src/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,32 @@ impl Value {
pub fn take(&mut self) -> Value {
mem::replace(self, Value::Null)
}

/// Reorders the entries of all `Value::Object` nested within this JSON
/// value according to `str`'s usual ordering.
///
/// If serde_json's "preserve_order" feature is not enabled, this method
/// does no work because all JSON maps are always kept in a sorted state.
///
/// If serde_json's "preserve_order" feature is enabled, this method
/// destroys the original source order or insertion order of the JSON
/// objects in favor of an alphanumerical order that matches how a BTreeMap
/// with the same contents would be ordered.
pub fn sort_all_objects(&mut self) {
#[cfg(feature = "preserve_order")]
{
match self {
Value::Object(map) => {
map.sort_keys();
map.values_mut().for_each(Value::sort_all_objects);
}
Value::Array(list) => {
list.iter_mut().for_each(Value::sort_all_objects);
}
_ => {}
}
}
}
}

/// The default value is `Value::Null`.
Expand Down

0 comments on commit 2679e30

Please sign in to comment.