Split JsonSchema implementations into separate files
This commit is contained in:
parent
a68b105450
commit
00148bdf57
11 changed files with 439 additions and 354 deletions
|
@ -1,354 +0,0 @@
|
|||
use crate::gen::{BoolSchemas, SchemaGenerator};
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
|
||||
// TODO any other serde/json types other than serde_json value?
|
||||
// TODO serde yaml value/map under feature flag
|
||||
// TODO add some inline attributes
|
||||
// https://github.com/serde-rs/serde/blob/ce75418e40a593fc5c0902cbf4a45305a4178dd7/serde/src/ser/impls.rs
|
||||
// Cell<T>, RefCell<T>, Mutex<T>, RwLock<T>, Result<R,E>?, Duration, SystemTime,
|
||||
// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6,
|
||||
// Path, PathBuf, OsStr, OsString, Wrapping<T>, Reverse<T>, AtomicBool, AtomixI8 etc.,
|
||||
// NonZeroU8 etc., ArcWeak, RcWeak, BTreeMap, HashMap, (!)?, Bound?, Range?, RangeInclusive?,
|
||||
// PhantomData?, CString?, CStr?, fmt::Arguments?
|
||||
|
||||
macro_rules! no_ref_schema {
|
||||
() => {
|
||||
fn is_referenceable() -> bool {
|
||||
false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////// PRIMITIVES //////////
|
||||
|
||||
macro_rules! simple_impl {
|
||||
($type:tt => $instance_type:ident) => {
|
||||
impl JsonSchema for $type {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
stringify!($instance_type).to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::$instance_type.into()),
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
simple_impl!(str => String);
|
||||
simple_impl!(String => String);
|
||||
simple_impl!(bool => Boolean);
|
||||
simple_impl!(f32 => Number);
|
||||
simple_impl!(f64 => Number);
|
||||
simple_impl!(i8 => Integer);
|
||||
simple_impl!(i16 => Integer);
|
||||
simple_impl!(i32 => Integer);
|
||||
simple_impl!(i64 => Integer);
|
||||
simple_impl!(i128 => Integer);
|
||||
simple_impl!(isize => Integer);
|
||||
simple_impl!(u8 => Integer);
|
||||
simple_impl!(u16 => Integer);
|
||||
simple_impl!(u32 => Integer);
|
||||
simple_impl!(u64 => Integer);
|
||||
simple_impl!(u128 => Integer);
|
||||
simple_impl!(usize => Integer);
|
||||
simple_impl!(() => Null);
|
||||
|
||||
impl JsonSchema for char {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Character".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minLength".to_owned(), json!(1));
|
||||
extensions.insert("maxLength".to_owned(), json!(1));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::String.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
////////// ARRAYS //////////
|
||||
|
||||
// Does not require T: JsonSchema.
|
||||
impl<T> JsonSchema for [T; 0] {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Empty_Array".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("maxItems".to_owned(), json!(0));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! array_impls {
|
||||
($($len:tt)+) => {
|
||||
$(
|
||||
impl<T: JsonSchema> JsonSchema for [T; $len] {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Array_Size_{}_Of_{}", $len, T::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minItems".to_owned(), json!($len));
|
||||
extensions.insert("maxItems".to_owned(), json!($len));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
items: Some(gen.subschema_for::<T>()?.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
array_impls! {
|
||||
1 2 3 4 5 6 7 8 9 10
|
||||
11 12 13 14 15 16 17 18 19 20
|
||||
21 22 23 24 25 26 27 28 29 30
|
||||
31 32
|
||||
}
|
||||
|
||||
////////// TUPLES //////////
|
||||
|
||||
macro_rules! tuple_impls {
|
||||
($($len:expr => ($($name:ident)+))+) => {
|
||||
$(
|
||||
impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
["Tuple_Of".to_owned()$(, $name::schema_name())+].join("_And_")
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minItems".to_owned(), json!($len));
|
||||
extensions.insert("maxItems".to_owned(), json!($len));
|
||||
let items = vec![
|
||||
$(gen.subschema_for::<$name>()?),+
|
||||
];
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
items: Some(items.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
tuple_impls! {
|
||||
1 => (T0)
|
||||
2 => (T0 T1)
|
||||
3 => (T0 T1 T2)
|
||||
4 => (T0 T1 T2 T3)
|
||||
5 => (T0 T1 T2 T3 T4)
|
||||
6 => (T0 T1 T2 T3 T4 T5)
|
||||
7 => (T0 T1 T2 T3 T4 T5 T6)
|
||||
8 => (T0 T1 T2 T3 T4 T5 T6 T7)
|
||||
9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8)
|
||||
10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9)
|
||||
11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
|
||||
12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11)
|
||||
13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
|
||||
14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
|
||||
15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
|
||||
16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
|
||||
}
|
||||
|
||||
////////// SEQUENCES /////////
|
||||
|
||||
macro_rules! seq_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+
|
||||
where
|
||||
T: JsonSchema,
|
||||
{
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Array_Of_{}", T::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
items: Some(gen.subschema_for::<T>()?.into()),
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
seq_impl!(<T: Ord> JsonSchema for std::collections::BinaryHeap<T>);
|
||||
seq_impl!(<T: Ord> JsonSchema for std::collections::BTreeSet<T>);
|
||||
seq_impl!(<T: Eq + core::hash::Hash, H: core::hash::BuildHasher> JsonSchema for std::collections::HashSet<T, H>);
|
||||
seq_impl!(<T> JsonSchema for std::collections::LinkedList<T>);
|
||||
seq_impl!(<T> JsonSchema for Vec<T>);
|
||||
seq_impl!(<T> JsonSchema for std::collections::VecDeque<T>);
|
||||
|
||||
////////// MAPS /////////
|
||||
|
||||
macro_rules! map_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+
|
||||
where
|
||||
K: Into<String>,
|
||||
V: JsonSchema,
|
||||
{
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Map_Of_{}", V::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let subschema = gen.subschema_for::<V>()?;
|
||||
let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly
|
||||
&& subschema == gen.schema_for_any();
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert(
|
||||
"additionalProperties".to_owned(),
|
||||
if json_schema_bool {
|
||||
json!(true)
|
||||
} else {
|
||||
json!(subschema)
|
||||
}
|
||||
);
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Object.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
map_impl!(<K: Ord, V> JsonSchema for std::collections::BTreeMap<K, V>);
|
||||
map_impl!(<K: Eq + core::hash::Hash, V, H: core::hash::BuildHasher> JsonSchema for std::collections::HashMap<K, V, H>);
|
||||
|
||||
////////// OPTION //////////
|
||||
|
||||
// TODO should a field with a default set also be considered nullable?
|
||||
|
||||
impl<T: JsonSchema> JsonSchema for Option<T> {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Nullable_{}", T::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut schema = if gen.settings().option_nullable {
|
||||
T::json_schema(gen)?
|
||||
} else {
|
||||
gen.subschema_for::<T>()?
|
||||
};
|
||||
if gen.settings().option_add_null_type {
|
||||
schema = match schema {
|
||||
Schema::Bool(true) => Schema::Bool(true),
|
||||
Schema::Bool(false) => <()>::json_schema(gen)?,
|
||||
schema => SchemaObject {
|
||||
any_of: Some(vec![schema, <()>::json_schema(gen)?]),
|
||||
..Default::default()
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
if gen.settings().option_nullable {
|
||||
let mut deref = gen.get_schema_object(&schema)?;
|
||||
deref.extensions.insert("nullable".to_owned(), json!(true));
|
||||
schema = Schema::Object(deref);
|
||||
};
|
||||
Ok(schema)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> JsonSchema for std::marker::PhantomData<T> {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
<()>::schema_name()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
<()>::json_schema(gen)
|
||||
}
|
||||
}
|
||||
|
||||
////////// DEREF //////////
|
||||
|
||||
macro_rules! deref_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+
|
||||
where
|
||||
T: ?Sized + JsonSchema,
|
||||
{
|
||||
fn is_referenceable() -> bool {
|
||||
T::is_referenceable()
|
||||
}
|
||||
|
||||
fn schema_name() -> String {
|
||||
T::schema_name()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
T::json_schema(gen)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
deref_impl!(<'a, T> JsonSchema for &'a T);
|
||||
deref_impl!(<'a, T> JsonSchema for &'a mut T);
|
||||
deref_impl!(<T> JsonSchema for Box<T>);
|
||||
deref_impl!(<T> JsonSchema for std::rc::Rc<T>);
|
||||
deref_impl!(<T> JsonSchema for std::sync::Arc<T>);
|
||||
deref_impl!(<'a, T: ToOwned> JsonSchema for std::borrow::Cow<'a, T>);
|
||||
|
||||
////////// SERDE_JSON //////////
|
||||
|
||||
impl JsonSchema for serde_json::Value {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Any_Value".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
Ok(gen.schema_for_any())
|
||||
}
|
||||
}
|
76
schemars/src/json_schema_impls/array.rs
Normal file
76
schemars/src/json_schema_impls/array.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
|
||||
// Does not require T: JsonSchema.
|
||||
impl<T> JsonSchema for [T; 0] {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Empty_Array".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("maxItems".to_owned(), json!(0));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! array_impls {
|
||||
($($len:tt)+) => {
|
||||
$(
|
||||
impl<T: JsonSchema> JsonSchema for [T; $len] {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Array_Size_{}_Of_{}", $len, T::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minItems".to_owned(), json!($len));
|
||||
extensions.insert("maxItems".to_owned(), json!($len));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
items: Some(gen.subschema_for::<T>()?.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
array_impls! {
|
||||
1 2 3 4 5 6 7 8 9 10
|
||||
11 12 13 14 15 16 17 18 19 20
|
||||
21 22 23 24 25 26 27 28 29 30
|
||||
31 32
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::tests::{schema_for, schema_object_for};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn schema_for_array() {
|
||||
let schema = schema_object_for::<[i32; 8]>();
|
||||
assert_eq!(
|
||||
schema.instance_type,
|
||||
Some(SingleOrVec::from(InstanceType::Array))
|
||||
);
|
||||
assert_eq!(schema.extensions.get("minItems"), Some(&json!(8)));
|
||||
assert_eq!(schema.extensions.get("maxItems"), Some(&json!(8)));
|
||||
assert_eq!(schema.items, Some(SingleOrVec::from(schema_for::<i32>())));
|
||||
}
|
||||
}
|
49
schemars/src/json_schema_impls/core.rs
Normal file
49
schemars/src/json_schema_impls/core.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Result};
|
||||
use serde_json::json;
|
||||
|
||||
impl<T: JsonSchema> JsonSchema for Option<T> {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Nullable_{}", T::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut schema = if gen.settings().option_nullable {
|
||||
T::json_schema(gen)?
|
||||
} else {
|
||||
gen.subschema_for::<T>()?
|
||||
};
|
||||
if gen.settings().option_add_null_type {
|
||||
schema = match schema {
|
||||
Schema::Bool(true) => Schema::Bool(true),
|
||||
Schema::Bool(false) => <()>::json_schema(gen)?,
|
||||
schema => SchemaObject {
|
||||
any_of: Some(vec![schema, <()>::json_schema(gen)?]),
|
||||
..Default::default()
|
||||
}
|
||||
.into(),
|
||||
}
|
||||
}
|
||||
if gen.settings().option_nullable {
|
||||
let mut deref = gen.get_schema_object(&schema)?;
|
||||
deref.extensions.insert("nullable".to_owned(), json!(true));
|
||||
schema = Schema::Object(deref);
|
||||
};
|
||||
Ok(schema)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> JsonSchema for std::marker::PhantomData<T> {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
<()>::schema_name()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
<()>::json_schema(gen)
|
||||
}
|
||||
}
|
30
schemars/src/json_schema_impls/deref.rs
Normal file
30
schemars/src/json_schema_impls/deref.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::{JsonSchema, Result};
|
||||
|
||||
macro_rules! deref_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+
|
||||
where
|
||||
T: ?Sized + JsonSchema,
|
||||
{
|
||||
fn is_referenceable() -> bool {
|
||||
T::is_referenceable()
|
||||
}
|
||||
|
||||
fn schema_name() -> String {
|
||||
T::schema_name()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
T::json_schema(gen)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
deref_impl!(<'a, T> JsonSchema for &'a T);
|
||||
deref_impl!(<'a, T> JsonSchema for &'a mut T);
|
||||
deref_impl!(<T> JsonSchema for Box<T>);
|
||||
deref_impl!(<T> JsonSchema for std::rc::Rc<T>);
|
||||
deref_impl!(<T> JsonSchema for std::sync::Arc<T>);
|
||||
deref_impl!(<'a, T: ToOwned> JsonSchema for std::borrow::Cow<'a, T>);
|
43
schemars/src/json_schema_impls/maps.rs
Normal file
43
schemars/src/json_schema_impls/maps.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use crate::gen::{BoolSchemas, SchemaGenerator};
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
|
||||
macro_rules! map_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+
|
||||
where
|
||||
K: Into<String>,
|
||||
V: JsonSchema,
|
||||
{
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Map_Of_{}", V::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let subschema = gen.subschema_for::<V>()?;
|
||||
let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly
|
||||
&& subschema == gen.schema_for_any();
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert(
|
||||
"additionalProperties".to_owned(),
|
||||
if json_schema_bool {
|
||||
json!(true)
|
||||
} else {
|
||||
json!(subschema)
|
||||
}
|
||||
);
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Object.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
map_impl!(<K: Ord, V> JsonSchema for std::collections::BTreeMap<K, V>);
|
||||
map_impl!(<K: Eq + core::hash::Hash, V, H: core::hash::BuildHasher> JsonSchema for std::collections::HashMap<K, V, H>);
|
25
schemars/src/json_schema_impls/mod.rs
Normal file
25
schemars/src/json_schema_impls/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
macro_rules! no_ref_schema {
|
||||
() => {
|
||||
fn is_referenceable() -> bool {
|
||||
false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mod array;
|
||||
mod core;
|
||||
mod deref;
|
||||
mod maps;
|
||||
mod primitives;
|
||||
mod sequences;
|
||||
mod serdejson;
|
||||
mod tuple;
|
||||
|
||||
// TODO chrono types under feature flag
|
||||
// TODO serde yaml value/map under feature flag
|
||||
// https://github.com/serde-rs/serde/blob/ce75418e40a593fc5c0902cbf4a45305a4178dd7/serde/src/ser/impls.rs
|
||||
// Cell<T>, RefCell<T>, Mutex<T>, RwLock<T>, Result<R,E>?, Duration, SystemTime,
|
||||
// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6,
|
||||
// Path, PathBuf, OsStr, OsString, Wrapping<T>, Reverse<T>, AtomicBool, AtomixI8 etc.,
|
||||
// NonZeroU8 etc., ArcWeak, RcWeak, (!)?, Bound?, Range?, RangeInclusive?,
|
||||
// CString?, CStr?, fmt::Arguments?
|
63
schemars/src/json_schema_impls/primitives.rs
Normal file
63
schemars/src/json_schema_impls/primitives.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
|
||||
macro_rules! simple_impl {
|
||||
($type:tt => $instance_type:ident) => {
|
||||
impl JsonSchema for $type {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
stringify!($instance_type).to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::$instance_type.into()),
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
simple_impl!(str => String);
|
||||
simple_impl!(String => String);
|
||||
simple_impl!(bool => Boolean);
|
||||
simple_impl!(f32 => Number);
|
||||
simple_impl!(f64 => Number);
|
||||
simple_impl!(i8 => Integer);
|
||||
simple_impl!(i16 => Integer);
|
||||
simple_impl!(i32 => Integer);
|
||||
simple_impl!(i64 => Integer);
|
||||
simple_impl!(i128 => Integer);
|
||||
simple_impl!(isize => Integer);
|
||||
simple_impl!(u8 => Integer);
|
||||
simple_impl!(u16 => Integer);
|
||||
simple_impl!(u32 => Integer);
|
||||
simple_impl!(u64 => Integer);
|
||||
simple_impl!(u128 => Integer);
|
||||
simple_impl!(usize => Integer);
|
||||
simple_impl!(() => Null);
|
||||
|
||||
impl JsonSchema for char {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Character".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minLength".to_owned(), json!(1));
|
||||
extensions.insert("maxLength".to_owned(), json!(1));
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::String.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
33
schemars/src/json_schema_impls/sequences.rs
Normal file
33
schemars/src/json_schema_impls/sequences.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Result};
|
||||
|
||||
macro_rules! seq_impl {
|
||||
($($desc:tt)+) => {
|
||||
impl $($desc)+
|
||||
where
|
||||
T: JsonSchema,
|
||||
{
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
format!("Array_Of_{}", T::schema_name())
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
items: Some(gen.subschema_for::<T>()?.into()),
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
seq_impl!(<T: Ord> JsonSchema for std::collections::BinaryHeap<T>);
|
||||
seq_impl!(<T: Ord> JsonSchema for std::collections::BTreeSet<T>);
|
||||
seq_impl!(<T: Eq + core::hash::Hash, H: core::hash::BuildHasher> JsonSchema for std::collections::HashSet<T, H>);
|
||||
seq_impl!(<T> JsonSchema for std::collections::LinkedList<T>);
|
||||
seq_impl!(<T> JsonSchema for Vec<T>);
|
||||
seq_impl!(<T> JsonSchema for std::collections::VecDeque<T>);
|
45
schemars/src/json_schema_impls/serdejson.rs
Normal file
45
schemars/src/json_schema_impls/serdejson.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Result};
|
||||
use serde_json::{Map, Number, Value};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
impl JsonSchema for Value {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Any_Value".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
Ok(gen.schema_for_any())
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSchema for Map<String, Value> {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
BTreeMap::<String, Value>::schema_name()
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
BTreeMap::<String, Value>::json_schema(gen)
|
||||
}
|
||||
}
|
||||
|
||||
impl JsonSchema for Number {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
"Number".to_owned()
|
||||
}
|
||||
|
||||
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Number.into()),
|
||||
..Default::default()
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
52
schemars/src/json_schema_impls/tuple.rs
Normal file
52
schemars/src/json_schema_impls/tuple.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::schema::*;
|
||||
use crate::{JsonSchema, Map, Result};
|
||||
use serde_json::json;
|
||||
|
||||
macro_rules! tuple_impls {
|
||||
($($len:expr => ($($name:ident)+))+) => {
|
||||
$(
|
||||
impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) {
|
||||
no_ref_schema!();
|
||||
|
||||
fn schema_name() -> String {
|
||||
["Tuple_Of".to_owned()$(, $name::schema_name())+].join("_And_")
|
||||
}
|
||||
|
||||
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert("minItems".to_owned(), json!($len));
|
||||
extensions.insert("maxItems".to_owned(), json!($len));
|
||||
let items = vec![
|
||||
$(gen.subschema_for::<$name>()?),+
|
||||
];
|
||||
Ok(SchemaObject {
|
||||
instance_type: Some(InstanceType::Array.into()),
|
||||
items: Some(items.into()),
|
||||
extensions,
|
||||
..Default::default()
|
||||
}.into())
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
tuple_impls! {
|
||||
1 => (T0)
|
||||
2 => (T0 T1)
|
||||
3 => (T0 T1 T2)
|
||||
4 => (T0 T1 T2 T3)
|
||||
5 => (T0 T1 T2 T3 T4)
|
||||
6 => (T0 T1 T2 T3 T4 T5)
|
||||
7 => (T0 T1 T2 T3 T4 T5 T6)
|
||||
8 => (T0 T1 T2 T3 T4 T5 T6 T7)
|
||||
9 => (T0 T1 T2 T3 T4 T5 T6 T7 T8)
|
||||
10 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9)
|
||||
11 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
|
||||
12 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11)
|
||||
13 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
|
||||
14 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
|
||||
15 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
|
||||
16 => (T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
|
||||
}
|
|
@ -23,3 +23,26 @@ pub trait JsonSchema {
|
|||
|
||||
fn json_schema(gen: &mut gen::SchemaGenerator) -> Result;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
|
||||
pub fn schema_for<T: JsonSchema>() -> schema::Schema {
|
||||
match T::json_schema(&mut gen::SchemaGenerator::default()) {
|
||||
Ok(s) => s,
|
||||
Err(e) => panic!(
|
||||
"Couldn't generate schema object for {}: {}",
|
||||
T::schema_name(),
|
||||
e
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn schema_object_for<T: JsonSchema>() -> schema::SchemaObject {
|
||||
match schema_for::<T>() {
|
||||
schema::Schema::Object(o) => o,
|
||||
s => panic!("Schema for {} was not an object: {:?}", T::schema_name(), s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue