diff --git a/schemars/src/_private.rs b/schemars/src/_private.rs new file mode 100644 index 0000000..4d1c31f --- /dev/null +++ b/schemars/src/_private.rs @@ -0,0 +1,49 @@ +use crate::flatten::Merge; +use crate::gen::SchemaGenerator; +use crate::schema::{Metadata, Schema, SchemaObject}; +use crate::JsonSchema; + +// Helper for generating schemas for flattened `Option` fields. +pub fn json_schema_for_flatten(gen: &mut SchemaGenerator) -> Schema { + let mut schema = T::_schemars_private_non_optional_json_schema(gen); + if T::_schemars_private_is_option() { + if let Schema::Object(SchemaObject { + object: Some(ref mut object_validation), + .. + }) = schema + { + object_validation.required.clear(); + } + } + schema +} + +// Helper for generating schemas for `Option` fields. +pub fn add_schema_as_property( + gen: &mut SchemaGenerator, + parent: &mut SchemaObject, + name: String, + metadata: Option, + required: bool, +) { + let mut schema = gen.subschema_for::(); + schema = apply_metadata(schema, metadata); + + let object = parent.object(); + if required && !T::_schemars_private_is_option() { + object.required.insert(name.clone()); + } + object.properties.insert(name, schema); +} + +pub fn apply_metadata(schema: Schema, metadata: Option) -> Schema { + match metadata { + None => schema, + Some(ref metadata) if *metadata == Metadata::default() => schema, + Some(metadata) => { + let mut schema_obj = schema.into_object(); + schema_obj.metadata = Some(Box::new(metadata)).merge(schema_obj.metadata); + Schema::Object(schema_obj) + } + } +} diff --git a/schemars/src/gen.rs b/schemars/src/gen.rs index 72c1700..2634e12 100644 --- a/schemars/src/gen.rs +++ b/schemars/src/gen.rs @@ -7,7 +7,6 @@ There are two main types in this module:two main types in this module: * [`SchemaGenerator`], which manages the generation of a schema document. */ -use crate::flatten::Merge; use crate::schema::*; use crate::{visit::*, JsonSchema, Map}; use dyn_clone::DynClone; @@ -422,22 +421,6 @@ impl SchemaGenerator { } } - /// This function is only public for use by schemars_derive. - /// - /// It should not be considered part of the public API. - #[doc(hidden)] - pub fn apply_metadata(&self, schema: Schema, metadata: Option) -> Schema { - match metadata { - None => schema, - Some(ref metadata) if *metadata == Metadata::default() => schema, - Some(metadata) => { - let mut schema_obj = schema.into_object(); - schema_obj.metadata = Some(Box::new(metadata)).merge(schema_obj.metadata); - Schema::Object(schema_obj) - } - } - } - fn json_schema_internal(&mut self, name: &str) -> Schema { struct PendingSchemaState<'a> { gen: &'a mut SchemaGenerator, diff --git a/schemars/src/json_schema_impls/core.rs b/schemars/src/json_schema_impls/core.rs index 5cefbdd..10f9f0f 100644 --- a/schemars/src/json_schema_impls/core.rs +++ b/schemars/src/json_schema_impls/core.rs @@ -45,30 +45,12 @@ impl JsonSchema for Option { schema } - fn json_schema_for_flatten(gen: &mut SchemaGenerator) -> Schema { - let mut schema = T::json_schema_for_flatten(gen); - if let Schema::Object(SchemaObject { - object: Some(ref mut object_validation), - .. - }) = schema - { - object_validation.required.clear(); - } - schema + fn _schemars_private_non_optional_json_schema(gen: &mut SchemaGenerator) -> Schema { + T::_schemars_private_non_optional_json_schema(gen) } - fn add_schema_as_property( - gen: &mut SchemaGenerator, - parent: &mut SchemaObject, - name: String, - metadata: Option, - _required: bool, - ) { - let mut schema = gen.subschema_for::(); - schema = gen.apply_metadata(schema, metadata); - - let object = parent.object(); - object.properties.insert(name, schema); + fn _schemars_private_is_option() -> bool { + true } } diff --git a/schemars/src/json_schema_impls/mod.rs b/schemars/src/json_schema_impls/mod.rs index d114ac4..ff2e1e7 100644 --- a/schemars/src/json_schema_impls/mod.rs +++ b/schemars/src/json_schema_impls/mod.rs @@ -21,18 +21,12 @@ macro_rules! forward_impl { <$target>::json_schema(gen) } - fn json_schema_for_flatten(gen: &mut SchemaGenerator) -> Schema { - <$target>::json_schema_for_flatten(gen) + fn _schemars_private_non_optional_json_schema(gen: &mut SchemaGenerator) -> Schema { + <$target>::_schemars_private_non_optional_json_schema(gen) } - fn add_schema_as_property( - gen: &mut SchemaGenerator, - parent: &mut crate::schema::SchemaObject, - name: String, - metadata: Option, - required: bool, - ) { - <$target>::add_schema_as_property(gen, parent, name, metadata, required) + fn _schemars_private_is_option() -> bool { + <$target>::_schemars_private_is_option() } } }; diff --git a/schemars/src/lib.rs b/schemars/src/lib.rs index 2957fc4..e400ccf 100644 --- a/schemars/src/lib.rs +++ b/schemars/src/lib.rs @@ -301,6 +301,10 @@ mod ser; #[macro_use] mod macros; +/// This module is only public for use by `schemars_derive`. It should not need to be used by code +/// outside of `schemars`, and should not be considered part of the public API. +#[doc(hidden)] +pub mod _private; pub mod gen; pub mod schema; pub mod visit; @@ -314,7 +318,7 @@ pub use schemars_derive::*; #[doc(hidden)] pub use serde_json as _serde_json; -use schema::{Schema, SchemaObject}; +use schema::Schema; /// A type which can be described as a JSON Schema document. /// @@ -357,35 +361,16 @@ pub trait JsonSchema { /// This should not return a `$ref` schema. fn json_schema(gen: &mut gen::SchemaGenerator) -> Schema; - /// Helper for generating schemas for flattened `Option` fields. - /// - /// This should not need to be called or implemented by code outside of `schemars`, - /// and should not be considered part of the public API. + // TODO document and bring into public API? #[doc(hidden)] - fn json_schema_for_flatten(gen: &mut gen::SchemaGenerator) -> Schema { + fn _schemars_private_non_optional_json_schema(gen: &mut gen::SchemaGenerator) -> Schema { Self::json_schema(gen) } - /// Helper for generating schemas for `Option` fields. - /// - /// This should not need to be called or implemented by code outside of `schemars`, - /// and should not be considered part of the public API. + // TODO document and bring into public API? #[doc(hidden)] - fn add_schema_as_property( - gen: &mut gen::SchemaGenerator, - parent: &mut SchemaObject, - name: String, - metadata: Option, - required: bool, - ) { - let mut schema = gen.subschema_for::(); - schema = gen.apply_metadata(schema, metadata); - - let object = parent.object(); - if required { - object.required.insert(name.clone()); - } - object.properties.insert(name, schema); + fn _schemars_private_is_option() -> bool { + false } } diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs index 11e026f..d536488 100644 --- a/schemars_derive/src/lib.rs +++ b/schemars_derive/src/lib.rs @@ -70,18 +70,12 @@ fn derive_json_schema( <#ty as schemars::JsonSchema>::json_schema(gen) } - fn json_schema_for_flatten(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - <#ty as schemars::JsonSchema>::json_schema_for_flatten(gen) + fn _schemars_private_non_optional_json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + <#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(gen) } - fn add_schema_as_property( - gen: &mut schemars::gen::SchemaGenerator, - parent: &mut schemars::schema::SchemaObject, - name: String, - metadata: Option, - required: bool, - ) { - <#ty as schemars::JsonSchema>::add_schema_as_property(gen, parent, name, metadata, required) + fn _schemars_private_is_option() -> bool { + <#ty as schemars::JsonSchema>::_schemars_private_is_option() } }; }; diff --git a/schemars_derive/src/metadata.rs b/schemars_derive/src/metadata.rs index 435469a..a84deca 100644 --- a/schemars_derive/src/metadata.rs +++ b/schemars_derive/src/metadata.rs @@ -49,7 +49,7 @@ impl<'a> SchemaMetadata<'a> { quote! { { let schema = #schema_expr; - gen.apply_metadata(schema, #self) + schemars::_private::apply_metadata(schema, #self) } } } diff --git a/schemars_derive/src/schema_exprs.rs b/schemars_derive/src/schema_exprs.rs index c5e83f2..f0f0c78 100644 --- a/schemars_derive/src/schema_exprs.rs +++ b/schemars_derive/src/schema_exprs.rs @@ -433,7 +433,7 @@ fn expr_for_struct( let args = quote!(gen, &mut schema_object, #name.to_owned(), #metadata, #required); quote_spanned! {ty.span()=> - <#ty as schemars::JsonSchema>::add_schema_as_property(#args); + schemars::_private::add_schema_as_property::<#ty>(#args); } }) .collect(); @@ -448,7 +448,7 @@ fn expr_for_struct( let gen = quote!(gen); quote_spanned! {ty.span()=> - .flatten(<#ty as schemars::JsonSchema>::json_schema_for_flatten(#gen)) + .flatten(schemars::_private::json_schema_for_flatten::<#ty>(#gen)) } }) .collect();