From a618a90eb4cf80171e6a276c6e305d8fb9dbd522 Mon Sep 17 00:00:00 2001 From: Ralph Bisschops Date: Sun, 7 Jun 2020 23:24:36 +0200 Subject: [PATCH] Adding `IndexMap` under feature flag `preserve_order` (#36) --- schemars/Cargo.toml | 7 ++++++- schemars/src/flatten.rs | 5 ++++- schemars/src/lib.rs | 21 +++++++++++++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/schemars/Cargo.toml b/schemars/Cargo.toml index 7d84eb6..cb727c9 100644 --- a/schemars/Cargo.toml +++ b/schemars/Cargo.toml @@ -19,7 +19,7 @@ serde_json = "1.0" dyn-clone = "1.0" chrono = { version = "0.4", default-features = false, optional = true } -indexmap = { version = "1.2", optional = true } +indexmap = { version = "1.2", features=["serde-1"], optional = true } either = { version = "1.3", default-features = false, optional = true } uuid = { version = "0.8", default-features = false, optional = true } smallvec = { version = "1.0", optional = true } @@ -34,6 +34,11 @@ default = ["derive"] derive = ["schemars_derive"] +# Use a different representation for the map type of Schemars. +# This allows data to be read into a Value and written back to a JSON string +# while preserving the order of map keys in the input. +preserve_order = ["indexmap"] + impl_json_schema = ["derive"] # derive_json_schema will be removed in a later version derive_json_schema = ["impl_json_schema"] diff --git a/schemars/src/flatten.rs b/schemars/src/flatten.rs index d3c777e..1e7dab3 100644 --- a/schemars/src/flatten.rs +++ b/schemars/src/flatten.rs @@ -101,7 +101,10 @@ impl Merge for Vec { } } -impl Merge for Map { +impl Merge for Map +where + K: std::hash::Hash + Eq + Ord, +{ fn merge(mut self, other: Self) -> Self { self.extend(other); self diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs index eb54638..cd2e068 100644 --- a/schemars/src/lib.rs +++ b/schemars/src/lib.rs @@ -197,8 +197,9 @@ fn main() { `#[serde(...)]` attributes can be overriden using `#[schemars(...)]` attributes, which behave identically (e.g. `#[schemars(rename_all = "camelCase")]`). You may find this useful if you want to change the generated schema without affecting Serde's behaviour, or if you're just not using Serde. ## Feature Flags -- `derive` (enabled by default) - provides `#[derive(JsonSchema)]` macro -- `impl_json_schema` - implements `JsonSchema` for Schemars types themselves +- `derive` (enabled by default) - provides `#[derive(JsonSchema)]` macro. +- `impl_json_schema` - implements `JsonSchema` for Schemars types themselves. +- `preserve_order` - keep the order of structure fields in `Schema` and `SchemaObject`. ## Optional Dependencies Schemars can implement `JsonSchema` on types from several popular crates, enabled via optional dependencies (dependency versions are shown in brackets): @@ -212,15 +213,27 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable /// The map type used by schemars types. /// -/// Currently a `BTreeMap`, but this may change a different implementation +/// Currently a `BTreeMap` or `IndexMap` can be used, but this may change to a different implementation /// with a similar interface in a future version of schemars. +/// The `IndexMap` will be used when the `preserve_order` feature flag is set. +#[cfg(not(feature = "preserve_order"))] pub type Map = std::collections::BTreeMap; +#[cfg(feature = "preserve_order")] +pub type Map = indexmap::IndexMap; /// The set type used by schemars types. /// -/// Currently a `BTreeSet`, but this may change a different implementation +/// Currently a `BTreeSet`, but this may change to a different implementation /// with a similar interface in a future version of schemars. pub type Set = std::collections::BTreeSet; +/// A view into a single entry in a map, which may either be vacant or occupied. +/// This is constructed from the `entry` method on `BTreeMap` or `IndexMap` +/// depending on whether the `preserve_order` feature flag is set. +#[cfg(not(feature = "preserve_order"))] +pub type MapEntry<'a, K, V> = std::collections::btree_map::Entry<'a, K, V>; +#[cfg(feature = "preserve_order")] +pub type MapEntry<'a, K, V> = indexmap::map::Entry<'a, K, V>; + mod flatten; mod json_schema_impls; #[macro_use]