use crate::gen::SchemaGenerator;
use crate::schema::{InstanceType, ObjectValidation, Schema, SchemaObject};
use crate::{JsonSchema, Map, Set};
use serde::Serialize;
use serde_json::Value;
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
gen: &mut SchemaGenerator,
required: bool,
) -> Schema {
let mut schema = T::_schemars_private_non_optional_json_schema(gen);
if T::_schemars_private_is_option() && !required {
if let Schema::Object(SchemaObject {
object: Some(ref mut object_validation),
..
}) = schema
{
object_validation.required.clear();
}
}
schema
}
#[doc(hidden)]
#[macro_export]
macro_rules! _schemars_maybe_to_value {
($expression:expr) => {{
#[allow(unused_imports)]
use $crate::_private::{MaybeSerializeWrapper, NoSerialize as _};
MaybeSerializeWrapper($expression).maybe_to_value()
}};
}
pub struct MaybeSerializeWrapper<T>(pub T);
pub trait NoSerialize: Sized {
fn maybe_to_value(self) -> Option<Value> {
None
}
}
impl<T> NoSerialize for T {}
impl<T: Serialize> MaybeSerializeWrapper<T> {
pub fn maybe_to_value(self) -> Option<Value> {
serde_json::value::to_value(self.0).ok()
}
}
pub fn new_unit_enum(variant: &str) -> Schema {
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(vec![variant.into()]),
..SchemaObject::default()
})
}
pub fn new_externally_tagged_enum(variant: &str, sub_schema: Schema) -> Schema {
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
properties: {
let mut props = Map::new();
props.insert(variant.to_owned(), sub_schema);
props
},
required: {
let mut required = Set::new();
required.insert(variant.to_owned());
required
},
additional_properties: Some(Box::new(false.into())),
..Default::default()
})),
..SchemaObject::default()
})
}
pub fn new_internally_tagged_enum(
tag_name: &str,
variant: &str,
deny_unknown_fields: bool,
) -> Schema {
let tag_schema = Schema::Object(SchemaObject {
instance_type: Some(InstanceType::String.into()),
enum_values: Some(vec![variant.into()]),
..Default::default()
});
Schema::Object(SchemaObject {
instance_type: Some(InstanceType::Object.into()),
object: Some(Box::new(ObjectValidation {
properties: {
let mut props = Map::new();
props.insert(tag_name.to_owned(), tag_schema);
props
},
required: {
let mut required = Set::new();
required.insert(tag_name.to_owned());
required
},
additional_properties: deny_unknown_fields.then(|| Box::new(false.into())),
..Default::default()
})),
..SchemaObject::default()
})
}
pub fn insert_object_property<T: ?Sized + JsonSchema>(
obj: &mut ObjectValidation,
key: &str,
has_default: bool,
required: bool,
schema: Schema,
) {
obj.properties.insert(key.to_owned(), schema);
if !has_default && (required || !T::_schemars_private_is_option()) {
obj.required.insert(key.to_owned());
}
}
pub mod metadata {
use crate::Schema;
use serde_json::Value;
macro_rules! add_metadata_fn {
($method:ident, $name:ident, $ty:ty) => {
pub fn $method(schema: Schema, $name: impl Into<$ty>) -> Schema {
let value = $name.into();
if value == <$ty>::default() {
schema
} else {
let mut schema_obj = schema.into_object();
schema_obj.metadata().$name = value.into();
Schema::Object(schema_obj)
}
}
};
}
add_metadata_fn!(add_description, description, String);
add_metadata_fn!(add_id, id, String);
add_metadata_fn!(add_title, title, String);
add_metadata_fn!(add_deprecated, deprecated, bool);
add_metadata_fn!(add_read_only, read_only, bool);
add_metadata_fn!(add_write_only, write_only, bool);
add_metadata_fn!(add_default, default, Option<Value>);
pub fn add_examples<I: IntoIterator<Item = Value>>(schema: Schema, examples: I) -> Schema {
let mut schema_obj = schema.into_object();
schema_obj.metadata().examples.extend(examples);
Schema::Object(schema_obj)
}
}