Add some config for openapi3 compatibility
This commit is contained in:
parent
ef5c584118
commit
1f514f2be7
3 changed files with 108 additions and 14 deletions
|
@ -4,19 +4,90 @@ use std::collections::BTreeMap as Map;
|
|||
use std::collections::BTreeSet as Set;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct SchemaSettings {
|
||||
pub option_nullable: bool,
|
||||
pub option_any_of_null: bool,
|
||||
pub bool_schemas: BoolSchemas,
|
||||
pub definitions_path: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum BoolSchemas {
|
||||
Enable,
|
||||
AdditionalPropertiesOnly,
|
||||
Disable,
|
||||
}
|
||||
|
||||
impl Default for SchemaSettings {
|
||||
fn default() -> SchemaSettings {
|
||||
SchemaSettings {
|
||||
option_nullable: false,
|
||||
option_any_of_null: true,
|
||||
bool_schemas: BoolSchemas::Enable,
|
||||
definitions_path: "#/definitions/".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SchemaSettings {
|
||||
pub fn new() -> SchemaSettings {
|
||||
SchemaSettings {
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
pub fn openapi3() -> SchemaSettings {
|
||||
SchemaSettings {
|
||||
option_nullable: true,
|
||||
option_any_of_null: false,
|
||||
bool_schemas: BoolSchemas::AdditionalPropertiesOnly,
|
||||
definitions_path: "#/components/schemas/".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_generator(self) -> SchemaGenerator {
|
||||
SchemaGenerator::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct SchemaGenerator {
|
||||
settings: SchemaSettings,
|
||||
names: Set<String>,
|
||||
definitions: Map<SchemaTypeId, (String, Schema)>,
|
||||
}
|
||||
|
||||
impl SchemaGenerator {
|
||||
pub fn new() -> SchemaGenerator {
|
||||
pub fn new(settings: SchemaSettings) -> SchemaGenerator {
|
||||
SchemaGenerator {
|
||||
settings,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn settings(&self) -> &SchemaSettings {
|
||||
&self.settings
|
||||
}
|
||||
|
||||
pub fn schema_for_any(&self) -> Schema {
|
||||
if self.settings().bool_schemas == BoolSchemas::Enable {
|
||||
true.into()
|
||||
} else {
|
||||
Schema::Object(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn schema_for_none(&self) -> Schema {
|
||||
if self.settings().bool_schemas == BoolSchemas::Enable {
|
||||
false.into()
|
||||
} else {
|
||||
Schema::Object(SchemaObject {
|
||||
not: Some(Schema::Object(Default::default()).into()),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn subschema_for<T: ?Sized + MakeSchema>(&mut self) -> Schema {
|
||||
if !T::generates_ref_schema() {
|
||||
return T::make_schema(self);
|
||||
|
@ -33,7 +104,7 @@ impl SchemaGenerator {
|
|||
self.insert_new_subschema_for::<T>(type_id, name.clone());
|
||||
name
|
||||
});
|
||||
let reference = format!("#/definitions/{}", name);
|
||||
let reference = format!("{}{}", self.settings().definitions_path, name);
|
||||
SchemaRef { reference }.into()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#[macro_export()]
|
||||
macro_rules! schema_for {
|
||||
($($type:tt)+) => {
|
||||
$crate::gen::SchemaGenerator::new().into_root_schema_for::<$($type)+>()
|
||||
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$($type)+>()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::gen::SchemaGenerator;
|
||||
use crate::gen::{BoolSchemas, SchemaGenerator};
|
||||
use crate::schema::*;
|
||||
use serde_json::json;
|
||||
use std::collections::BTreeMap as Map;
|
||||
|
@ -233,10 +233,17 @@ macro_rules! map_impl {
|
|||
|
||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema
|
||||
{
|
||||
let subschema = gen.subschema_for::<V>();
|
||||
let make_schema_bool = gen.settings().bool_schemas == BoolSchemas::AdditionalPropertiesOnly
|
||||
&& subschema == gen.schema_for_any();
|
||||
let mut extensions = Map::new();
|
||||
extensions.insert(
|
||||
"additionalProperties".to_owned(),
|
||||
json!(gen.subschema_for::<V>())
|
||||
if make_schema_bool {
|
||||
json!(true)
|
||||
} else {
|
||||
json!(subschema)
|
||||
}
|
||||
);
|
||||
SchemaObject {
|
||||
instance_type: Some(InstanceType::Object.into()),
|
||||
|
@ -257,16 +264,32 @@ impl<T: MakeSchema> MakeSchema for Option<T> {
|
|||
no_ref_schema!();
|
||||
|
||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||
match gen.subschema_for::<T>() {
|
||||
let settings = gen.settings();
|
||||
let make_any_of = settings.option_any_of_null;
|
||||
let set_nullable = settings.option_nullable;
|
||||
let mut schema = match gen.subschema_for::<T>() {
|
||||
Schema::Bool(true) => true.into(),
|
||||
Schema::Bool(false) => <()>::make_schema(gen),
|
||||
schema => SchemaObject {
|
||||
schema => {
|
||||
if make_any_of {
|
||||
SchemaObject {
|
||||
any_of: Some(vec![schema, <()>::make_schema(gen)]),
|
||||
..Default::default()
|
||||
}
|
||||
.into(),
|
||||
.into()
|
||||
} else {
|
||||
schema
|
||||
}
|
||||
}
|
||||
};
|
||||
if set_nullable {
|
||||
// FIXME still need to handle ref schemas here
|
||||
if let Schema::Object(ref mut o) = schema {
|
||||
o.extensions.insert("nullable".to_owned(), true.into());
|
||||
}
|
||||
};
|
||||
schema
|
||||
}
|
||||
}
|
||||
|
||||
////////// DEREF //////////
|
||||
|
@ -298,7 +321,7 @@ deref_impl!(<'a, T: ToOwned> MakeSchema for std::borrow::Cow<'a, T>);
|
|||
impl MakeSchema for serde_json::Value {
|
||||
no_ref_schema!();
|
||||
|
||||
fn make_schema(_: &mut SchemaGenerator) -> Schema {
|
||||
true.into()
|
||||
fn make_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||
gen.schema_for_any()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue