From addac6d386d3241fb730e5d3f0826a04f8f61aed Mon Sep 17 00:00:00 2001 From: Alastair Feille Date: Sun, 21 Mar 2021 09:43:58 -0500 Subject: [PATCH] Make HashSet and BTreeSet use the uniqueItems keyword in their schema (#64) Co-authored-by: Graham Esau --- CHANGELOG.md | 1 + schemars/src/json_schema_impls/sequences.rs | 33 +++++++++++++++++-- schemars/tests/expected/indexmap.json | 3 +- .../tests/expected/remote_derive_generic.json | 3 +- schemars/tests/expected/schema-2019_09.json | 6 ++-- schemars/tests/expected/schema-openapi3.json | 6 ++-- schemars/tests/expected/schema.json | 6 ++-- 7 files changed, 48 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf633b8..b60f0d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Changed: - Minimum supported rust version is now 1.37.0 - Deriving JsonSchema on enums now sets `additionalProperties` to false on generated schemas wherever serde doesn't accept unknown properties. This includes non-unit variants of externally tagged enums, and struct-style variants of all enums that have the `deny_unknown_fields` attribute. +- Schemas for HashSet and BTreeSet now have `uniqueItems` set to true (https://github.com/GREsau/schemars/pull/64) ### Fixed - Fix use of `#[serde(transparent)]` in combination with `#[schemars(with = ...)]` (https://github.com/GREsau/schemars/pull/67) diff --git a/schemars/src/json_schema_impls/sequences.rs b/schemars/src/json_schema_impls/sequences.rs index 1e79210..632a01e 100644 --- a/schemars/src/json_schema_impls/sequences.rs +++ b/schemars/src/json_schema_impls/sequences.rs @@ -29,9 +29,38 @@ macro_rules! seq_impl { }; } +macro_rules! set_impl { + ($($desc:tt)+) => { + impl $($desc)+ + where + T: JsonSchema, + { + no_ref_schema!(); + + fn schema_name() -> String { + format!("Set_of_{}", T::schema_name()) + } + + fn json_schema(gen: &mut SchemaGenerator) -> Schema { + SchemaObject { + instance_type: Some(InstanceType::Array.into()), + array: Some(Box::new(ArrayValidation { + unique_items: Some(true), + items: Some(gen.subschema_for::().into()), + ..Default::default() + })), + ..Default::default() + } + .into() + } + } + }; +} + + seq_impl!( JsonSchema for std::collections::BinaryHeap); -seq_impl!( JsonSchema for std::collections::BTreeSet); -seq_impl!( JsonSchema for std::collections::HashSet); +set_impl!( JsonSchema for std::collections::BTreeSet); +set_impl!( JsonSchema for std::collections::HashSet); seq_impl!( JsonSchema for std::collections::LinkedList); seq_impl!( JsonSchema for Vec); seq_impl!( JsonSchema for std::collections::VecDeque); diff --git a/schemars/tests/expected/indexmap.json b/schemars/tests/expected/indexmap.json index e9d4df4..98065d9 100644 --- a/schemars/tests/expected/indexmap.json +++ b/schemars/tests/expected/indexmap.json @@ -18,7 +18,8 @@ "items": { "type": "integer", "format": "int" - } + }, + "uniqueItems": true } } } \ No newline at end of file diff --git a/schemars/tests/expected/remote_derive_generic.json b/schemars/tests/expected/remote_derive_generic.json index c76610c..2fea80a 100644 --- a/schemars/tests/expected/remote_derive_generic.json +++ b/schemars/tests/expected/remote_derive_generic.json @@ -24,7 +24,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true } } }, diff --git a/schemars/tests/expected/schema-2019_09.json b/schemars/tests/expected/schema-2019_09.json index 33a063b..cf11d35 100644 --- a/schemars/tests/expected/schema-2019_09.json +++ b/schemars/tests/expected/schema-2019_09.json @@ -315,7 +315,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true }, "properties": { "description": "The `properties` keyword.\n\nSee [JSON Schema 9.3.2.1. \"properties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).", @@ -670,7 +671,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true }, "properties": { "description": "The `properties` keyword.\n\nSee [JSON Schema 9.3.2.1. \"properties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).", diff --git a/schemars/tests/expected/schema-openapi3.json b/schemars/tests/expected/schema-openapi3.json index 78deb95..0548828 100644 --- a/schemars/tests/expected/schema-openapi3.json +++ b/schemars/tests/expected/schema-openapi3.json @@ -255,7 +255,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true }, "properties": { "description": "The `properties` keyword.\n\nSee [JSON Schema 9.3.2.1. \"properties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).", @@ -552,7 +553,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true }, "properties": { "description": "The `properties` keyword.\n\nSee [JSON Schema 9.3.2.1. \"properties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).", diff --git a/schemars/tests/expected/schema.json b/schemars/tests/expected/schema.json index b54d0a2..6cf840b 100644 --- a/schemars/tests/expected/schema.json +++ b/schemars/tests/expected/schema.json @@ -315,7 +315,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true }, "properties": { "description": "The `properties` keyword.\n\nSee [JSON Schema 9.3.2.1. \"properties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).", @@ -674,7 +675,8 @@ "type": "array", "items": { "type": "string" - } + }, + "uniqueItems": true }, "properties": { "description": "The `properties` keyword.\n\nSee [JSON Schema 9.3.2.1. \"properties\"](https://tools.ietf.org/html/draft-handrews-json-schema-02#section-9.3.2.1).",