Rename MakeSchema to JsonSchema
This commit is contained in:
parent
58e169b866
commit
870dc3a2de
16 changed files with 117 additions and 130 deletions
|
@ -2,7 +2,7 @@
|
||||||
name = "schemars"
|
name = "schemars"
|
||||||
description = "Generate JSON Schemas from Rust code"
|
description = "Generate JSON Schemas from Rust code"
|
||||||
repository = "https://github.com/GREsau/schemars"
|
repository = "https://github.com/GREsau/schemars"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
@ -2,25 +2,25 @@ use std::fmt;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use crate::schema::Schema;
|
use crate::schema::Schema;
|
||||||
|
|
||||||
pub type Result<T = Schema> = std::result::Result<T, MakeSchemaError>;
|
pub type Result<T = Schema> = std::result::Result<T, JsonSchemaError>;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MakeSchemaError {
|
pub struct JsonSchemaError {
|
||||||
msg: &'static str,
|
msg: &'static str,
|
||||||
schema: Schema
|
schema: Schema
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MakeSchemaError {
|
impl JsonSchemaError {
|
||||||
pub fn new(msg: &'static str, schema: Schema) -> MakeSchemaError {
|
pub fn new(msg: &'static str, schema: Schema) -> JsonSchemaError {
|
||||||
MakeSchemaError { msg, schema }
|
JsonSchemaError { msg, schema }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for MakeSchemaError {
|
impl fmt::Display for JsonSchemaError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{} Schema: {:?}", self.msg, self.schema)
|
write!(f, "{} Schema: {:?}", self.msg, self.schema)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error for MakeSchemaError {
|
impl Error for JsonSchemaError {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::make_schema::MakeSchema;
|
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use crate::{MakeSchemaError, Map, Result};
|
use crate::{JsonSchema, JsonSchemaError, Map, Result};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct SchemaSettings {
|
pub struct SchemaSettings {
|
||||||
|
@ -85,9 +84,9 @@ impl SchemaGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subschema_for<T: ?Sized + MakeSchema>(&mut self) -> Result {
|
pub fn subschema_for<T: ?Sized + JsonSchema>(&mut self) -> Result {
|
||||||
if !T::is_referenceable() {
|
if !T::is_referenceable() {
|
||||||
return T::make_schema(self);
|
return T::json_schema(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = T::schema_name();
|
let name = T::schema_name();
|
||||||
|
@ -98,12 +97,12 @@ impl SchemaGenerator {
|
||||||
Ok(Ref { reference }.into())
|
Ok(Ref { reference }.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_new_subschema_for<T: ?Sized + MakeSchema>(&mut self, name: String) -> Result<()> {
|
fn insert_new_subschema_for<T: ?Sized + JsonSchema>(&mut self, name: String) -> Result<()> {
|
||||||
let dummy = Schema::Bool(false);
|
let dummy = Schema::Bool(false);
|
||||||
// insert into definitions BEFORE calling make_schema to avoid infinite recursion
|
// insert into definitions BEFORE calling json_schema to avoid infinite recursion
|
||||||
self.definitions.insert(name.clone(), dummy);
|
self.definitions.insert(name.clone(), dummy);
|
||||||
|
|
||||||
match T::make_schema(self) {
|
match T::json_schema(self) {
|
||||||
Ok(schema) => {
|
Ok(schema) => {
|
||||||
self.definitions.insert(name.clone(), schema);
|
self.definitions.insert(name.clone(), schema);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -123,8 +122,8 @@ impl SchemaGenerator {
|
||||||
self.definitions
|
self.definitions
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn root_schema_for<T: ?Sized + MakeSchema>(&mut self) -> Result {
|
pub fn root_schema_for<T: ?Sized + JsonSchema>(&mut self) -> Result {
|
||||||
let schema = T::make_schema(self)?;
|
let schema = T::json_schema(self)?;
|
||||||
Ok(match schema {
|
Ok(match schema {
|
||||||
Schema::Object(mut o) => {
|
Schema::Object(mut o) => {
|
||||||
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
||||||
|
@ -136,8 +135,8 @@ impl SchemaGenerator {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_root_schema_for<T: ?Sized + MakeSchema>(mut self) -> Result {
|
pub fn into_root_schema_for<T: ?Sized + JsonSchema>(mut self) -> Result {
|
||||||
let schema = T::make_schema(&mut self)?;
|
let schema = T::json_schema(&mut self)?;
|
||||||
Ok(match schema {
|
Ok(match schema {
|
||||||
Schema::Object(mut o) => {
|
Schema::Object(mut o) => {
|
||||||
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
o.schema = Some("http://json-schema.org/draft-07/schema#".to_owned());
|
||||||
|
@ -163,14 +162,14 @@ impl SchemaGenerator {
|
||||||
Schema::Ref(r) => {
|
Schema::Ref(r) => {
|
||||||
let definitions_path_len = self.settings().definitions_path.len();
|
let definitions_path_len = self.settings().definitions_path.len();
|
||||||
let name = r.reference.get(definitions_path_len..).ok_or_else(|| {
|
let name = r.reference.get(definitions_path_len..).ok_or_else(|| {
|
||||||
MakeSchemaError::new(
|
JsonSchemaError::new(
|
||||||
"Could not extract referenced schema name.",
|
"Could not extract referenced schema name.",
|
||||||
Schema::Ref(r.clone()),
|
Schema::Ref(r.clone()),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
schema = self.definitions.get(name).ok_or_else(|| {
|
schema = self.definitions.get(name).ok_or_else(|| {
|
||||||
MakeSchemaError::new(
|
JsonSchemaError::new(
|
||||||
"Could not find referenced schema.",
|
"Could not find referenced schema.",
|
||||||
Schema::Ref(r.clone()),
|
Schema::Ref(r.clone()),
|
||||||
)
|
)
|
||||||
|
@ -178,7 +177,7 @@ impl SchemaGenerator {
|
||||||
|
|
||||||
match schema {
|
match schema {
|
||||||
Schema::Ref(r2) if r2 == r => {
|
Schema::Ref(r2) if r2 == r => {
|
||||||
return Err(MakeSchemaError::new(
|
return Err(JsonSchemaError::new(
|
||||||
"Schema is referencing itself.",
|
"Schema is referencing itself.",
|
||||||
schema.clone(),
|
schema.clone(),
|
||||||
));
|
));
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
use crate::gen::{BoolSchemas, SchemaGenerator};
|
use crate::gen::{BoolSchemas, SchemaGenerator};
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use crate::{Map, Result};
|
use crate::{JsonSchema, Map, Result};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
pub trait MakeSchema {
|
|
||||||
fn is_referenceable() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn schema_name() -> String;
|
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO any other serde/json types other than serde_json value?
|
// TODO any other serde/json types other than serde_json value?
|
||||||
// TODO serde yaml value/map under feature flag
|
// TODO serde yaml value/map under feature flag
|
||||||
// TODO add some inline attributes
|
// TODO add some inline attributes
|
||||||
|
@ -35,14 +25,14 @@ macro_rules! no_ref_schema {
|
||||||
|
|
||||||
macro_rules! simple_impl {
|
macro_rules! simple_impl {
|
||||||
($type:tt => $instance_type:ident) => {
|
($type:tt => $instance_type:ident) => {
|
||||||
impl MakeSchema for $type {
|
impl JsonSchema for $type {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
stringify!($instance_type).to_owned()
|
stringify!($instance_type).to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(_: &mut SchemaGenerator) -> Result {
|
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||||
Ok(SchemaObject {
|
Ok(SchemaObject {
|
||||||
instance_type: Some(InstanceType::$instance_type.into()),
|
instance_type: Some(InstanceType::$instance_type.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -72,14 +62,14 @@ simple_impl!(u128 => Integer);
|
||||||
simple_impl!(usize => Integer);
|
simple_impl!(usize => Integer);
|
||||||
simple_impl!(() => Null);
|
simple_impl!(() => Null);
|
||||||
|
|
||||||
impl MakeSchema for char {
|
impl JsonSchema for char {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
"Character".to_owned()
|
"Character".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(_: &mut SchemaGenerator) -> Result {
|
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||||
let mut extensions = Map::new();
|
let mut extensions = Map::new();
|
||||||
extensions.insert("minLength".to_owned(), json!(1));
|
extensions.insert("minLength".to_owned(), json!(1));
|
||||||
extensions.insert("maxLength".to_owned(), json!(1));
|
extensions.insert("maxLength".to_owned(), json!(1));
|
||||||
|
@ -94,15 +84,15 @@ impl MakeSchema for char {
|
||||||
|
|
||||||
////////// ARRAYS //////////
|
////////// ARRAYS //////////
|
||||||
|
|
||||||
// Does not require T: MakeSchema.
|
// Does not require T: JsonSchema.
|
||||||
impl<T> MakeSchema for [T; 0] {
|
impl<T> JsonSchema for [T; 0] {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
"Empty_Array".to_owned()
|
"Empty_Array".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(_: &mut SchemaGenerator) -> Result {
|
fn json_schema(_: &mut SchemaGenerator) -> Result {
|
||||||
let mut extensions = Map::new();
|
let mut extensions = Map::new();
|
||||||
extensions.insert("maxItems".to_owned(), json!(0));
|
extensions.insert("maxItems".to_owned(), json!(0));
|
||||||
Ok(SchemaObject {
|
Ok(SchemaObject {
|
||||||
|
@ -117,14 +107,14 @@ impl<T> MakeSchema for [T; 0] {
|
||||||
macro_rules! array_impls {
|
macro_rules! array_impls {
|
||||||
($($len:tt)+) => {
|
($($len:tt)+) => {
|
||||||
$(
|
$(
|
||||||
impl<T: MakeSchema> MakeSchema for [T; $len] {
|
impl<T: JsonSchema> JsonSchema for [T; $len] {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
format!("Array_Size_{}_Of_{}", $len, T::schema_name())
|
format!("Array_Size_{}_Of_{}", $len, T::schema_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
let mut extensions = Map::new();
|
let mut extensions = Map::new();
|
||||||
extensions.insert("minItems".to_owned(), json!($len));
|
extensions.insert("minItems".to_owned(), json!($len));
|
||||||
extensions.insert("maxItems".to_owned(), json!($len));
|
extensions.insert("maxItems".to_owned(), json!($len));
|
||||||
|
@ -152,14 +142,14 @@ array_impls! {
|
||||||
macro_rules! tuple_impls {
|
macro_rules! tuple_impls {
|
||||||
($($len:expr => ($($name:ident)+))+) => {
|
($($len:expr => ($($name:ident)+))+) => {
|
||||||
$(
|
$(
|
||||||
impl<$($name: MakeSchema),+> MakeSchema for ($($name,)+) {
|
impl<$($name: JsonSchema),+> JsonSchema for ($($name,)+) {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
["Tuple_Of".to_owned()$(, $name::schema_name())+].join("_And_")
|
["Tuple_Of".to_owned()$(, $name::schema_name())+].join("_And_")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
let mut extensions = Map::new();
|
let mut extensions = Map::new();
|
||||||
extensions.insert("minItems".to_owned(), json!($len));
|
extensions.insert("minItems".to_owned(), json!($len));
|
||||||
extensions.insert("maxItems".to_owned(), json!($len));
|
extensions.insert("maxItems".to_owned(), json!($len));
|
||||||
|
@ -203,7 +193,7 @@ macro_rules! seq_impl {
|
||||||
($($desc:tt)+) => {
|
($($desc:tt)+) => {
|
||||||
impl $($desc)+
|
impl $($desc)+
|
||||||
where
|
where
|
||||||
T: MakeSchema,
|
T: JsonSchema,
|
||||||
{
|
{
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
|
@ -211,7 +201,7 @@ macro_rules! seq_impl {
|
||||||
format!("Array_Of_{}", T::schema_name())
|
format!("Array_Of_{}", T::schema_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
Ok(SchemaObject {
|
Ok(SchemaObject {
|
||||||
instance_type: Some(InstanceType::Array.into()),
|
instance_type: Some(InstanceType::Array.into()),
|
||||||
items: Some(gen.subschema_for::<T>()?.into()),
|
items: Some(gen.subschema_for::<T>()?.into()),
|
||||||
|
@ -222,12 +212,12 @@ macro_rules! seq_impl {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_impl!(<T: Ord> MakeSchema for std::collections::BinaryHeap<T>);
|
seq_impl!(<T: Ord> JsonSchema for std::collections::BinaryHeap<T>);
|
||||||
seq_impl!(<T: Ord> MakeSchema for std::collections::BTreeSet<T>);
|
seq_impl!(<T: Ord> JsonSchema for std::collections::BTreeSet<T>);
|
||||||
seq_impl!(<T: Eq + core::hash::Hash, H: core::hash::BuildHasher> MakeSchema for std::collections::HashSet<T, H>);
|
seq_impl!(<T: Eq + core::hash::Hash, H: core::hash::BuildHasher> JsonSchema for std::collections::HashSet<T, H>);
|
||||||
seq_impl!(<T> MakeSchema for std::collections::LinkedList<T>);
|
seq_impl!(<T> JsonSchema for std::collections::LinkedList<T>);
|
||||||
seq_impl!(<T> MakeSchema for Vec<T>);
|
seq_impl!(<T> JsonSchema for Vec<T>);
|
||||||
seq_impl!(<T> MakeSchema for std::collections::VecDeque<T>);
|
seq_impl!(<T> JsonSchema for std::collections::VecDeque<T>);
|
||||||
|
|
||||||
////////// MAPS /////////
|
////////// MAPS /////////
|
||||||
|
|
||||||
|
@ -236,7 +226,7 @@ macro_rules! map_impl {
|
||||||
impl $($desc)+
|
impl $($desc)+
|
||||||
where
|
where
|
||||||
K: Into<String>,
|
K: Into<String>,
|
||||||
V: MakeSchema,
|
V: JsonSchema,
|
||||||
{
|
{
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
|
@ -244,14 +234,14 @@ macro_rules! map_impl {
|
||||||
format!("Map_Of_{}", V::schema_name())
|
format!("Map_Of_{}", V::schema_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
let subschema = gen.subschema_for::<V>()?;
|
let subschema = gen.subschema_for::<V>()?;
|
||||||
let make_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly
|
let json_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly
|
||||||
&& subschema == gen.schema_for_any();
|
&& subschema == gen.schema_for_any();
|
||||||
let mut extensions = Map::new();
|
let mut extensions = Map::new();
|
||||||
extensions.insert(
|
extensions.insert(
|
||||||
"additionalProperties".to_owned(),
|
"additionalProperties".to_owned(),
|
||||||
if make_schema_bool {
|
if json_schema_bool {
|
||||||
json!(true)
|
json!(true)
|
||||||
} else {
|
} else {
|
||||||
json!(subschema)
|
json!(subschema)
|
||||||
|
@ -267,30 +257,30 @@ macro_rules! map_impl {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
map_impl!(<K: Ord, V> MakeSchema for std::collections::BTreeMap<K, V>);
|
map_impl!(<K: Ord, V> JsonSchema for std::collections::BTreeMap<K, V>);
|
||||||
map_impl!(<K: Eq + core::hash::Hash, V, H: core::hash::BuildHasher> MakeSchema for std::collections::HashMap<K, V, H>);
|
map_impl!(<K: Eq + core::hash::Hash, V, H: core::hash::BuildHasher> JsonSchema for std::collections::HashMap<K, V, H>);
|
||||||
|
|
||||||
////////// OPTION //////////
|
////////// OPTION //////////
|
||||||
|
|
||||||
// TODO should a field with a default set also be considered nullable?
|
// TODO should a field with a default set also be considered nullable?
|
||||||
|
|
||||||
impl<T: MakeSchema> MakeSchema for Option<T> {
|
impl<T: JsonSchema> JsonSchema for Option<T> {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
format!("Nullable_{}", T::schema_name())
|
format!("Nullable_{}", T::schema_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
// FIXME this may produce a subschema that is not referenced in the final schema,
|
// FIXME this may produce a subschema that is not referenced in the final schema,
|
||||||
// e.g. SingleOrVec_For_InstanceType in schema-openapi3.json
|
// e.g. SingleOrVec_For_InstanceType in schema-openapi3.json
|
||||||
let mut schema = gen.subschema_for::<T>()?;
|
let mut schema = gen.subschema_for::<T>()?;
|
||||||
if gen.settings().option_add_null_type {
|
if gen.settings().option_add_null_type {
|
||||||
schema = match schema {
|
schema = match schema {
|
||||||
Schema::Bool(true) => Schema::Bool(true),
|
Schema::Bool(true) => Schema::Bool(true),
|
||||||
Schema::Bool(false) => <()>::make_schema(gen)?,
|
Schema::Bool(false) => <()>::json_schema(gen)?,
|
||||||
schema => SchemaObject {
|
schema => SchemaObject {
|
||||||
any_of: Some(vec![schema, <()>::make_schema(gen)?]),
|
any_of: Some(vec![schema, <()>::json_schema(gen)?]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -305,15 +295,15 @@ impl<T: MakeSchema> MakeSchema for Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> MakeSchema for std::marker::PhantomData<T> {
|
impl<T> JsonSchema for std::marker::PhantomData<T> {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
<()>::schema_name()
|
<()>::schema_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
<()>::make_schema(gen)
|
<()>::json_schema(gen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +313,7 @@ macro_rules! deref_impl {
|
||||||
($($desc:tt)+) => {
|
($($desc:tt)+) => {
|
||||||
impl $($desc)+
|
impl $($desc)+
|
||||||
where
|
where
|
||||||
T: MakeSchema,
|
T: JsonSchema,
|
||||||
{
|
{
|
||||||
fn is_referenceable() -> bool {
|
fn is_referenceable() -> bool {
|
||||||
T::is_referenceable()
|
T::is_referenceable()
|
||||||
|
@ -333,30 +323,30 @@ macro_rules! deref_impl {
|
||||||
T::schema_name()
|
T::schema_name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
T::make_schema(gen)
|
T::json_schema(gen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
deref_impl!(<'a, T> MakeSchema for &'a T);
|
deref_impl!(<'a, T> JsonSchema for &'a T);
|
||||||
deref_impl!(<'a, T> MakeSchema for &'a mut T);
|
deref_impl!(<'a, T> JsonSchema for &'a mut T);
|
||||||
deref_impl!(<T> MakeSchema for Box<T>);
|
deref_impl!(<T> JsonSchema for Box<T>);
|
||||||
deref_impl!(<T> MakeSchema for std::rc::Rc<T>);
|
deref_impl!(<T> JsonSchema for std::rc::Rc<T>);
|
||||||
deref_impl!(<T> MakeSchema for std::sync::Arc<T>);
|
deref_impl!(<T> JsonSchema for std::sync::Arc<T>);
|
||||||
deref_impl!(<'a, T: ToOwned> MakeSchema for std::borrow::Cow<'a, T>);
|
deref_impl!(<'a, T: ToOwned> JsonSchema for std::borrow::Cow<'a, T>);
|
||||||
|
|
||||||
////////// SERDE_JSON //////////
|
////////// SERDE_JSON //////////
|
||||||
|
|
||||||
impl MakeSchema for serde_json::Value {
|
impl JsonSchema for serde_json::Value {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
"Any_Value".to_owned()
|
"Any_Value".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut SchemaGenerator) -> Result {
|
fn json_schema(gen: &mut SchemaGenerator) -> Result {
|
||||||
Ok(gen.schema_for_any())
|
Ok(gen.schema_for_any())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,15 +1,23 @@
|
||||||
pub type Map<K, V> = std::collections::BTreeMap<K, V>;
|
pub type Map<K, V> = std::collections::BTreeMap<K, V>;
|
||||||
pub type Set<T> = std::collections::BTreeSet<T>;
|
pub type Set<T> = std::collections::BTreeSet<T>;
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
mod json_schema_impls;
|
||||||
|
#[macro_use]
|
||||||
|
mod macros;
|
||||||
|
|
||||||
pub mod gen;
|
pub mod gen;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
|
|
||||||
mod error;
|
|
||||||
mod make_schema;
|
|
||||||
#[macro_use]
|
|
||||||
mod macros;
|
|
||||||
|
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
pub use make_schema::MakeSchema;
|
|
||||||
|
|
||||||
pub use schemars_derive::*;
|
pub use schemars_derive::*;
|
||||||
|
|
||||||
|
pub trait JsonSchema {
|
||||||
|
fn is_referenceable() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema_name() -> String;
|
||||||
|
|
||||||
|
fn json_schema(gen: &mut gen::SchemaGenerator) -> Result;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#[macro_export()]
|
#[macro_export]
|
||||||
macro_rules! schema_for {
|
macro_rules! schema_for {
|
||||||
($($type:tt)+) => {
|
($($type:tt)+) => {
|
||||||
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$($type)+>()
|
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$($type)+>()
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
use schemars::{schema_for, schema::Schema};
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
let schema = schema_for!(Schema)?;
|
|
||||||
let json = serde_json::to_string_pretty(&schema)?;
|
|
||||||
println!("{}", json);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate as schemars;
|
use crate as schemars;
|
||||||
use crate::{MakeSchema, MakeSchemaError, Map, Result, Set};
|
use crate::{JsonSchema, JsonSchemaError, Map, Result, Set};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, MakeSchema)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum Schema {
|
pub enum Schema {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
|
@ -62,7 +62,7 @@ impl Schema {
|
||||||
let s = match self {
|
let s = match self {
|
||||||
Schema::Object(s) => s,
|
Schema::Object(s) => s,
|
||||||
s => {
|
s => {
|
||||||
return Err(MakeSchemaError::new(
|
return Err(JsonSchemaError::new(
|
||||||
"Only schemas with type `object` can be flattened.",
|
"Only schemas with type `object` can be flattened.",
|
||||||
s,
|
s,
|
||||||
))
|
))
|
||||||
|
@ -70,13 +70,13 @@ impl Schema {
|
||||||
};
|
};
|
||||||
match s.instance_type {
|
match s.instance_type {
|
||||||
Some(SingleOrVec::Single(ref t)) if **t != InstanceType::Object => {
|
Some(SingleOrVec::Single(ref t)) if **t != InstanceType::Object => {
|
||||||
Err(MakeSchemaError::new(
|
Err(JsonSchemaError::new(
|
||||||
"Only schemas with type `object` can be flattened.",
|
"Only schemas with type `object` can be flattened.",
|
||||||
s.into(),
|
s.into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Some(SingleOrVec::Vec(ref t)) if !t.contains(&InstanceType::Object) => {
|
Some(SingleOrVec::Vec(ref t)) if !t.contains(&InstanceType::Object) => {
|
||||||
Err(MakeSchemaError::new(
|
Err(JsonSchemaError::new(
|
||||||
"Only schemas with type `object` can be flattened.",
|
"Only schemas with type `object` can be flattened.",
|
||||||
s.into(),
|
s.into(),
|
||||||
))
|
))
|
||||||
|
@ -86,13 +86,13 @@ impl Schema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, MakeSchema)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema)]
|
||||||
pub struct Ref {
|
pub struct Ref {
|
||||||
#[serde(rename = "$ref")]
|
#[serde(rename = "$ref")]
|
||||||
pub reference: String,
|
pub reference: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, MakeSchema)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase", default)]
|
#[serde(rename_all = "camelCase", default)]
|
||||||
pub struct SchemaObject {
|
pub struct SchemaObject {
|
||||||
#[serde(rename = "$schema", skip_serializing_if = "Option::is_none")]
|
#[serde(rename = "$schema", skip_serializing_if = "Option::is_none")]
|
||||||
|
@ -127,7 +127,7 @@ pub struct SchemaObject {
|
||||||
pub extensions: Map<String, Value>,
|
pub extensions: Map<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, MakeSchema)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum InstanceType {
|
pub enum InstanceType {
|
||||||
Null,
|
Null,
|
||||||
|
@ -139,7 +139,7 @@ pub enum InstanceType {
|
||||||
Integer,
|
Integer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, MakeSchema)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum SingleOrVec<T> {
|
pub enum SingleOrVec<T> {
|
||||||
Single(Box<T>),
|
Single(Box<T>),
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
mod util;
|
mod util;
|
||||||
use schemars::{MakeSchema, Map};
|
use schemars::{JsonSchema, Map};
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(rename_all = "camelCase")]
|
#[schemars(rename_all = "camelCase")]
|
||||||
pub enum External {
|
pub enum External {
|
||||||
UnitOne,
|
UnitOne,
|
||||||
|
@ -16,7 +16,7 @@ fn enum_external_tag() -> TestResult {
|
||||||
test_default_generated_schema::<External>("enum-external")
|
test_default_generated_schema::<External>("enum-external")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(tag = "typeProperty")]
|
#[schemars(tag = "typeProperty")]
|
||||||
pub enum Internal {
|
pub enum Internal {
|
||||||
UnitOne,
|
UnitOne,
|
||||||
|
@ -30,7 +30,7 @@ fn enum_internal_tag() -> TestResult {
|
||||||
test_default_generated_schema::<Internal>("enum-internal")
|
test_default_generated_schema::<Internal>("enum-internal")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(untagged)]
|
#[schemars(untagged)]
|
||||||
pub enum Untagged {
|
pub enum Untagged {
|
||||||
UnitOne,
|
UnitOne,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
mod util;
|
mod util;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use schemars::{schema_for, MakeSchema};
|
use schemars::{schema_for, JsonSchema};
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
struct Flat {
|
struct Flat {
|
||||||
foo: f32,
|
foo: f32,
|
||||||
bar: bool,
|
bar: bool,
|
||||||
|
@ -11,7 +11,7 @@ struct Flat {
|
||||||
foobar: Vec<i32>,
|
foobar: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(rename = "Flat")]
|
#[schemars(rename = "Flat")]
|
||||||
struct Deep1 {
|
struct Deep1 {
|
||||||
foo: f32,
|
foo: f32,
|
||||||
|
@ -20,14 +20,14 @@ struct Deep1 {
|
||||||
foobar: Vec<i32>,
|
foobar: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
struct Deep2 {
|
struct Deep2 {
|
||||||
bar: bool,
|
bar: bool,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
deep3: Deep3,
|
deep3: Deep3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
struct Deep3 {
|
struct Deep3 {
|
||||||
baz: String,
|
baz: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
mod util;
|
mod util;
|
||||||
use schemars::MakeSchema;
|
use schemars::JsonSchema;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
struct MyStruct {
|
struct MyStruct {
|
||||||
camel_case: i32,
|
camel_case: i32,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
mod util;
|
mod util;
|
||||||
use schemars::MakeSchema;
|
use schemars::JsonSchema;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
struct MyStruct<T, U, V, W> {
|
struct MyStruct<T, U, V, W> {
|
||||||
t: T,
|
t: T,
|
||||||
u: U,
|
u: U,
|
||||||
|
@ -11,7 +11,7 @@ struct MyStruct<T, U, V, W> {
|
||||||
inner: MySimpleStruct,
|
inner: MySimpleStruct,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
struct MySimpleStruct {}
|
struct MySimpleStruct {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -19,7 +19,7 @@ fn default_name_multiple_type_params() -> TestResult {
|
||||||
test_default_generated_schema::<MyStruct<i32, (), bool, Vec<String>>>("schema-name-default")
|
test_default_generated_schema::<MyStruct<i32, (), bool, Vec<String>>>("schema-name-default")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[serde(rename = "a-new-name-{W}-{T}-{T}")]
|
#[serde(rename = "a-new-name-{W}-{T}-{T}")]
|
||||||
struct MyRenamedStruct<T, U, V, W> {
|
struct MyRenamedStruct<T, U, V, W> {
|
||||||
t: T,
|
t: T,
|
||||||
|
@ -29,7 +29,7 @@ struct MyRenamedStruct<T, U, V, W> {
|
||||||
inner: MySimpleRenamedStruct,
|
inner: MySimpleRenamedStruct,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, MakeSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[serde(rename = "this-attribute-is-ignored")]
|
#[serde(rename = "this-attribute-is-ignored")]
|
||||||
#[schemars(rename = "another-new-name")]
|
#[schemars(rename = "another-new-name")]
|
||||||
struct MySimpleRenamedStruct {}
|
struct MySimpleRenamedStruct {}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use schemars::{gen::SchemaSettings, schema_for, MakeSchema};
|
use schemars::{gen::SchemaSettings, schema_for, JsonSchema};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::panic;
|
use std::panic;
|
||||||
|
@ -7,7 +7,7 @@ use std::panic;
|
||||||
pub type TestResult = Result<(), Box<dyn Error>>;
|
pub type TestResult = Result<(), Box<dyn Error>>;
|
||||||
|
|
||||||
#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/46379
|
#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/46379
|
||||||
pub fn test_generated_schema<T: MakeSchema>(file: &str, settings: SchemaSettings) -> TestResult {
|
pub fn test_generated_schema<T: JsonSchema>(file: &str, settings: SchemaSettings) -> TestResult {
|
||||||
let expected_json = fs::read_to_string(format!("tests/expected/{}.json", file))?;
|
let expected_json = fs::read_to_string(format!("tests/expected/{}.json", file))?;
|
||||||
let expected = serde_json::from_str(&expected_json)?;
|
let expected = serde_json::from_str(&expected_json)?;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ pub fn test_generated_schema<T: MakeSchema>(file: &str, settings: SchemaSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/46379
|
#[allow(dead_code)] // https://github.com/rust-lang/rust/issues/46379
|
||||||
pub fn test_default_generated_schema<T: MakeSchema>(file: &str) -> TestResult {
|
pub fn test_default_generated_schema<T: JsonSchema>(file: &str) -> TestResult {
|
||||||
let expected_json = fs::read_to_string(format!("tests/expected/{}.json", file))?;
|
let expected_json = fs::read_to_string(format!("tests/expected/{}.json", file))?;
|
||||||
let expected = serde_json::from_str(&expected_json)?;
|
let expected = serde_json::from_str(&expected_json)?;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
[package]
|
[package]
|
||||||
name = "schemars_derive"
|
name = "schemars_derive"
|
||||||
description = "Macros for #[derive(MakeSchema)], for use with schemars"
|
description = "Macros for #[derive(JsonSchema)], for use with schemars"
|
||||||
repository = "https://github.com/GREsau/schemars"
|
repository = "https://github.com/GREsau/schemars"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
@ -14,8 +14,8 @@ use serde_derive_internals::{Ctxt, Derive};
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::DeriveInput;
|
use syn::DeriveInput;
|
||||||
|
|
||||||
#[proc_macro_derive(MakeSchema, attributes(schemars, serde))]
|
#[proc_macro_derive(JsonSchema, attributes(schemars, serde))]
|
||||||
pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_json_schema(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let mut input = parse_macro_input!(input as DeriveInput);
|
let mut input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
preprocess::add_trait_bounds(&mut input.generics);
|
preprocess::add_trait_bounds(&mut input.generics);
|
||||||
|
@ -64,12 +64,12 @@ pub fn derive_make_schema(input: proc_macro::TokenStream) -> proc_macro::TokenSt
|
||||||
|
|
||||||
let impl_block = quote! {
|
let impl_block = quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl #impl_generics schemars::MakeSchema for #type_name #ty_generics #where_clause {
|
impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause {
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
#schema_name
|
#schema_name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Result {
|
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Result {
|
||||||
Ok(#schema)
|
Ok(#schema)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -256,7 +256,7 @@ fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream
|
||||||
let flattens = flat.iter().map(|f| {
|
let flattens = flat.iter().map(|f| {
|
||||||
let ty = f.ty;
|
let ty = f.ty;
|
||||||
quote_spanned! {f.original.span()=>
|
quote_spanned! {f.original.span()=>
|
||||||
.flatten(<#ty>::make_schema(gen)?)?
|
.flatten(<#ty>::json_schema(gen)?)?
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use syn::{Attribute, Data, DeriveInput, Field, GenericParam, Generics, Ident, Va
|
||||||
pub fn add_trait_bounds(generics: &mut Generics) {
|
pub fn add_trait_bounds(generics: &mut Generics) {
|
||||||
for param in &mut generics.params {
|
for param in &mut generics.params {
|
||||||
if let GenericParam::Type(ref mut type_param) = *param {
|
if let GenericParam::Type(ref mut type_param) = *param {
|
||||||
type_param.bounds.push(parse_quote!(schemars::MakeSchema));
|
type_param.bounds.push(parse_quote!(schemars::JsonSchema));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue