From 3c03d910caa7dcbc5a3ae52141cd51d8039d2d3e Mon Sep 17 00:00:00 2001 From: Graham Esau Date: Sat, 3 Aug 2019 19:16:30 +0100 Subject: [PATCH] Allow boolean "trivial" schemas --- schemars/src/make_schema.rs | 40 +++++++++++++++++++---------------- schemars/src/schema.rs | 42 +++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/schemars/src/make_schema.rs b/schemars/src/make_schema.rs index 37fecda..3f07def 100644 --- a/schemars/src/make_schema.rs +++ b/schemars/src/make_schema.rs @@ -23,10 +23,11 @@ macro_rules! simple_impl { ($type:tt => $instance_type:expr) => { impl MakeSchema for $type { fn make_schema() -> Schema { - Schema { + SchemaObject { instance_type: Some($instance_type.into()), ..Default::default() } + .into() } } }; @@ -44,11 +45,12 @@ impl MakeSchema for char { let mut extra_properties = Map::new(); extra_properties.insert("minLength".to_owned(), json!(1)); extra_properties.insert("maxLength".to_owned(), json!(1)); - Schema { + SchemaObject { instance_type: Some(InstanceType::String.into()), extra_properties, ..Default::default() } + .into() } } @@ -62,11 +64,12 @@ macro_rules! int_impl { // this may be overkill... extra_properties.insert("minimum".to_owned(), json!($type::min_value())); extra_properties.insert("maximum".to_owned(), json!($type::max_value())); - Schema { + SchemaObject { instance_type: Some(InstanceType::Integer.into()), extra_properties, ..Default::default() } + .into() } } }; @@ -92,11 +95,12 @@ impl MakeSchema for [T; 0] { fn make_schema() -> Schema { let mut extra_properties = Map::new(); extra_properties.insert("maxItems".to_owned(), json!(0)); - Schema { + SchemaObject { instance_type: Some(InstanceType::Array.into()), extra_properties, ..Default::default() } + .into() } } @@ -109,12 +113,12 @@ macro_rules! array_impls { let mut extra_properties = Map::new(); extra_properties.insert("minItems".to_owned(), json!($len)); extra_properties.insert("maxItems".to_owned(), json!($len)); - Schema { + SchemaObject { instance_type: Some(InstanceType::Array.into()), items: Some(Box::from(T::make_schema())), extra_properties, ..Default::default() - } + }.into() } } )+ @@ -138,11 +142,11 @@ macro_rules! seq_impl { { fn make_schema() -> Schema { - Schema { + SchemaObject { instance_type: Some(InstanceType::Array.into()), items: Some(Box::from(T::make_schema())), ..Default::default() - } + }.into() } } }; @@ -171,11 +175,11 @@ macro_rules! map_impl { "additionalProperties".to_owned(), json!(T::make_schema()) ); - Schema { + SchemaObject { instance_type: Some(InstanceType::Object.into()), extra_properties, ..Default::default() - } + }.into() } } }; @@ -188,15 +192,15 @@ map_impl!( MakeSchema f impl MakeSchema for Option { fn make_schema() -> Schema { - let mut schema = T::make_schema(); - if let Some(instance_type) = schema.instance_type { - let mut vec: Vec<_> = instance_type.into(); - if !vec.contains(&InstanceType::Null) { - vec.push(InstanceType::Null); + match T::make_schema() { + Schema::Bool(true) => true.into(), + Schema::Bool(false) => <()>::make_schema(), + Schema::Object(schema) => SchemaObject { + any_of: Some(vec![schema.into(), <()>::make_schema()]), + ..Default::default() } - schema.instance_type = Some(vec.into()); + .into(), } - schema } } @@ -226,6 +230,6 @@ deref_impl!(<'a, T: ToOwned> MakeSchema for std::borrow::Cow<'a, T>); impl MakeSchema for serde_json::Value { fn make_schema() -> Schema { - Schema::default() + true.into() } } diff --git a/schemars/src/schema.rs b/schemars/src/schema.rs index 436c257..3a97a2b 100644 --- a/schemars/src/schema.rs +++ b/schemars/src/schema.rs @@ -2,22 +2,34 @@ use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::BTreeMap as Map; +#[derive(Serialize, Deserialize, Debug)] +#[serde(untagged)] +pub enum Schema { + Bool(bool), + Object(SchemaObject), +} + +impl From for Schema { + fn from(o: SchemaObject) -> Self { + Schema::Object(o) + } +} + +impl From for Schema { + fn from(b: bool) -> Self { + Schema::Bool(b) + } +} + #[derive(Serialize, Deserialize, Debug, Default)] #[serde(rename_all = "camelCase")] -pub struct RootSchema { +pub struct SchemaObject { #[serde(rename = "$schema", skip_serializing_if = "Option::is_none")] pub schema: Option, #[serde(skip_serializing_if = "Option::is_none")] pub title: Option, #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, - #[serde(flatten)] - pub root: Schema, -} - -#[derive(Serialize, Deserialize, Debug, Default)] -#[serde(rename_all = "camelCase")] -pub struct Schema { #[serde(rename = "$id", skip_serializing_if = "Option::is_none")] pub id: Option, #[serde(rename = "type", skip_serializing_if = "Option::is_none")] @@ -26,6 +38,14 @@ pub struct Schema { pub instance_enum: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub items: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub all_of: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub any_of: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub one_of: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub not: Option>, #[serde(skip_serializing_if = "Map::is_empty")] pub definitions: Map, #[serde(flatten)] @@ -75,14 +95,14 @@ impl Into> for SingleOrVec { } } -/*pub struct Schema { +/*pub struct SchemaObject { pub ref_path: Option, pub description: Option, pub schema_type: Option, pub format: Option, pub enum_values: Option>, pub required: Option>, - pub items: Option>, - pub properties: Option>, + pub items: Option>, + pub properties: Option>, } */