Add documentation comments, rename Visitor2
This commit is contained in:
parent
0c02525fb9
commit
460976e765
6 changed files with 92 additions and 42 deletions
|
@ -14,8 +14,8 @@
|
||||||
- `SchemaSettings` no longer implements `PartialEq`
|
- `SchemaSettings` no longer implements `PartialEq`
|
||||||
- `SchemaGenerator::into_definitions()` - this has been superseded by `SchemaGenerator::take_definitions()`
|
- `SchemaGenerator::into_definitions()` - this has been superseded by `SchemaGenerator::take_definitions()`
|
||||||
|
|
||||||
### Changed (**BREAKING CHANGES**):
|
### Changed:
|
||||||
- Minimum supported rust version is now 1.36.0
|
- **BREAKING CHANGE** Minimum supported rust version is now 1.36.0
|
||||||
|
|
||||||
### Fixed:
|
### Fixed:
|
||||||
- **BREAKING CHANGE** unknown items in `#[schemars(...)]` attributes now cause a compilation error (https://github.com/GREsau/schemars/issues/18)
|
- **BREAKING CHANGE** unknown items in `#[schemars(...)]` attributes now cause a compilation error (https://github.com/GREsau/schemars/issues/18)
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
/*!
|
||||||
|
JSON Schema generator and settings.
|
||||||
|
|
||||||
|
This module is useful if you want more control over how the schema generated then the [`schema_for!`] macro gives you.
|
||||||
|
There are two main types in this module:two main types in this module:
|
||||||
|
* [`SchemaSettings`], which defines what JSON Schema features should be used when generating schemas (for example, how `Option`s should be represented).
|
||||||
|
* [`SchemaGenerator`], which manages the generation of a schema document.
|
||||||
|
*/
|
||||||
|
|
||||||
use crate::flatten::Merge;
|
use crate::flatten::Merge;
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use crate::{visit::*, JsonSchema, Map};
|
use crate::{visit::*, JsonSchema, Map};
|
||||||
|
@ -29,7 +38,7 @@ pub struct SchemaSettings {
|
||||||
/// Defaults to `"http://json-schema.org/draft-07/schema#"`.
|
/// Defaults to `"http://json-schema.org/draft-07/schema#"`.
|
||||||
pub meta_schema: Option<String>,
|
pub meta_schema: Option<String>,
|
||||||
/// A list of visitors that get applied to all generated root schemas.
|
/// A list of visitors that get applied to all generated root schemas.
|
||||||
pub visitors: Vec<Box<dyn Visitor2>>,
|
pub visitors: Vec<Box<dyn GenVisitor>>,
|
||||||
_hidden: (),
|
_hidden: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +114,7 @@ impl SchemaSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Appends the given visitor to the list of [visitors](SchemaSettings::visitors) for these `SchemaSettings`.
|
/// Appends the given visitor to the list of [visitors](SchemaSettings::visitors) for these `SchemaSettings`.
|
||||||
pub fn with_visitor(mut self, visitor: impl Visitor + Debug + DynClone + 'static) -> Self {
|
pub fn with_visitor(mut self, visitor: impl Visitor + Debug + Clone + 'static) -> Self {
|
||||||
self.visitors.push(Box::new(visitor));
|
self.visitors.push(Box::new(visitor));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -225,7 +234,7 @@ impl SchemaGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the [visitors](SchemaSettings::visitors) being used by this `SchemaGenerator`.
|
/// Returns an iterator over the [visitors](SchemaSettings::visitors) being used by this `SchemaGenerator`.
|
||||||
pub fn visitors_mut(&mut self) -> impl Iterator<Item = &mut dyn Visitor2> {
|
pub fn visitors_mut(&mut self) -> impl Iterator<Item = &mut dyn GenVisitor> {
|
||||||
self.settings.visitors.iter_mut().map(|v| v.as_mut())
|
self.settings.visitors.iter_mut().map(|v| v.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,31 +345,31 @@ impl SchemaGenerator {
|
||||||
/// - [`Visitor`]
|
/// - [`Visitor`]
|
||||||
/// - [`std::fmt::Debug`]
|
/// - [`std::fmt::Debug`]
|
||||||
/// - [`std::any::Any`] (implemented for all `'static` types)
|
/// - [`std::any::Any`] (implemented for all `'static` types)
|
||||||
/// - [`dyn_clone::DynClone`] (or [`std::clone::Clone`])
|
/// - [`std::clone::Clone`]
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use schemars::visit::Visitor;
|
/// use schemars::visit::Visitor;
|
||||||
/// use schemars::gen::Visitor2;
|
/// use schemars::gen::GenVisitor;
|
||||||
///
|
///
|
||||||
/// #[derive(Debug, Clone)]
|
/// #[derive(Debug, Clone)]
|
||||||
/// struct MyVisitor;
|
/// struct MyVisitor;
|
||||||
///
|
///
|
||||||
/// impl Visitor for MyVisitor { }
|
/// impl Visitor for MyVisitor { }
|
||||||
///
|
///
|
||||||
/// let v: &dyn Visitor2 = &MyVisitor;
|
/// let v: &dyn GenVisitor = &MyVisitor;
|
||||||
/// assert_eq!(v.as_any().is::<MyVisitor>(), true);
|
/// assert!(v.as_any().is::<MyVisitor>());
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Visitor2: Visitor + Debug + DynClone + Any {
|
pub trait GenVisitor: Visitor + Debug + DynClone + Any {
|
||||||
/// Upcasts this visitor into an `Any`, which can be used to inspect and manipulate it as its concrete type.
|
/// Upcasts this visitor into an `Any`, which can be used to inspect and manipulate it as its concrete type.
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
dyn_clone::clone_trait_object!(Visitor2);
|
dyn_clone::clone_trait_object!(GenVisitor);
|
||||||
|
|
||||||
impl<T> Visitor2 for T
|
impl<T> GenVisitor for T
|
||||||
where
|
where
|
||||||
T: Visitor + Debug + DynClone + Any,
|
T: Visitor + Debug + Clone + Any,
|
||||||
{
|
{
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
|
|
|
@ -227,7 +227,8 @@ pub type Map<K, V> = indexmap::IndexMap<K, V>;
|
||||||
pub type Set<T> = std::collections::BTreeSet<T>;
|
pub type Set<T> = std::collections::BTreeSet<T>;
|
||||||
|
|
||||||
/// A view into a single entry in a map, which may either be vacant or occupied.
|
/// A view into a single entry in a map, which may either be vacant or occupied.
|
||||||
/// This is constructed from the `entry` method on `BTreeMap` or `IndexMap`
|
//
|
||||||
|
/// This is constructed from the `entry` method on `BTreeMap` or `IndexMap`,
|
||||||
/// depending on whether the `preserve_order` feature flag is set.
|
/// depending on whether the `preserve_order` feature flag is set.
|
||||||
#[cfg(not(feature = "preserve_order"))]
|
#[cfg(not(feature = "preserve_order"))]
|
||||||
pub type MapEntry<'a, K, V> = std::collections::btree_map::Entry<'a, K, V>;
|
pub type MapEntry<'a, K, V> = std::collections::btree_map::Entry<'a, K, V>;
|
||||||
|
@ -239,11 +240,8 @@ mod json_schema_impls;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
/// JSON Schema generator and settings.
|
|
||||||
pub mod gen;
|
pub mod gen;
|
||||||
/// JSON Schema types.
|
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
/// TODO document
|
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
|
||||||
#[cfg(feature = "schemars_derive")]
|
#[cfg(feature = "schemars_derive")]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/// Generates a [`RootSchema`](schema::RootSchema) for the given type using default settings.
|
/// Generates a [`RootSchema`](crate::schema::RootSchema) for the given type using default settings.
|
||||||
///
|
///
|
||||||
/// The type must implement [`JsonSchema`].
|
/// The type must implement [`JsonSchema`](crate::JsonSchema).
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/*!
|
||||||
|
JSON Schema types.
|
||||||
|
*/
|
||||||
|
|
||||||
#[cfg(feature = "impl_json_schema")]
|
#[cfg(feature = "impl_json_schema")]
|
||||||
use crate as schemars;
|
use crate as schemars;
|
||||||
#[cfg(feature = "impl_json_schema")]
|
#[cfg(feature = "impl_json_schema")]
|
||||||
|
|
|
@ -1,37 +1,70 @@
|
||||||
|
/*!
|
||||||
|
Contains the [`Visitor`] trait, used to recursively modify a constructed schema and its subschemas.
|
||||||
|
|
||||||
|
Sometimes you may want to apply a change to a schema, as well as all schemas contained within it.
|
||||||
|
The easiest way to achieve this is by defining a type that implements [`Visitor`].
|
||||||
|
All methods of `Visitor` have a default implementation that makes no change but recursively visits all subschemas.
|
||||||
|
When overriding one of these methods, you will *usually* want to still call this default implementation.
|
||||||
|
|
||||||
|
# Example
|
||||||
|
To add a custom property to all schemas:
|
||||||
|
```
|
||||||
|
use schemars::schema::SchemaObject;
|
||||||
|
use schemars::visit::{Visitor, visit_schema_object};
|
||||||
|
|
||||||
|
pub struct MyVisitor;
|
||||||
|
|
||||||
|
impl Visitor for MyVisitor {
|
||||||
|
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
|
||||||
|
// First, make our change to this schema
|
||||||
|
schema.extensions.insert("my_property".to_string(), serde_json::json!("hello world"));
|
||||||
|
|
||||||
|
// Then delegate to default implementation to visit any subschemas
|
||||||
|
visit_schema_object(self, schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
*/
|
||||||
use crate::schema::{RootSchema, Schema, SchemaObject, SingleOrVec};
|
use crate::schema::{RootSchema, Schema, SchemaObject, SingleOrVec};
|
||||||
|
|
||||||
/// TODO document
|
/// Trait used to recursively modify a constructed schema and its subschemas.
|
||||||
pub trait Visitor {
|
pub trait Visitor {
|
||||||
/// TODO document
|
/// Override this method to modify a [`RootSchema`] and (optionally) its subschemas.
|
||||||
|
///
|
||||||
|
/// When overriding this method, you will usually want to call the [`visit_root_schema`] function to visit subschemas.
|
||||||
fn visit_root_schema(&mut self, root: &mut RootSchema) {
|
fn visit_root_schema(&mut self, root: &mut RootSchema) {
|
||||||
visit_root_schema(self, root)
|
visit_root_schema(self, root)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// Override this method to modify a [`Schema`] and (optionally) its subschemas.
|
||||||
|
///
|
||||||
|
/// When overriding this method, you will usually want to call the [`visit_schema`] function to visit subschemas.
|
||||||
fn visit_schema(&mut self, schema: &mut Schema) {
|
fn visit_schema(&mut self, schema: &mut Schema) {
|
||||||
visit_schema(self, schema)
|
visit_schema(self, schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// Override this method to modify a [`SchemaObject`] and (optionally) its subschemas.
|
||||||
|
///
|
||||||
|
/// When overriding this method, you will usually want to call the [`visit_schema_object`] function to visit subschemas.
|
||||||
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
|
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
|
||||||
visit_schema_object(self, schema)
|
visit_schema_object(self, schema)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// Visits all subschemas of the [`RootSchema`].
|
||||||
pub fn visit_root_schema<V: Visitor + ?Sized>(v: &mut V, root: &mut RootSchema) {
|
pub fn visit_root_schema<V: Visitor + ?Sized>(v: &mut V, root: &mut RootSchema) {
|
||||||
v.visit_schema_object(&mut root.schema);
|
v.visit_schema_object(&mut root.schema);
|
||||||
visit_map_values(v, &mut root.definitions);
|
visit_map_values(v, &mut root.definitions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// Visits all subschemas of the [`Schema`].
|
||||||
pub fn visit_schema<V: Visitor + ?Sized>(v: &mut V, schema: &mut Schema) {
|
pub fn visit_schema<V: Visitor + ?Sized>(v: &mut V, schema: &mut Schema) {
|
||||||
if let Schema::Object(schema) = schema {
|
if let Schema::Object(schema) = schema {
|
||||||
v.visit_schema_object(schema)
|
v.visit_schema_object(schema)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// Visits all subschemas of the [`SchemaObject`].
|
||||||
pub fn visit_schema_object<V: Visitor + ?Sized>(v: &mut V, schema: &mut SchemaObject) {
|
pub fn visit_schema_object<V: Visitor + ?Sized>(v: &mut V, schema: &mut SchemaObject) {
|
||||||
if let Some(sub) = &mut schema.subschemas {
|
if let Some(sub) = &mut schema.subschemas {
|
||||||
visit_vec(v, &mut sub.all_of);
|
visit_vec(v, &mut sub.all_of);
|
||||||
|
@ -89,10 +122,12 @@ fn visit_single_or_vec<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<Singl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// This visitor will replace all boolean JSON Schemas with equivalent object schemas.
|
||||||
|
///
|
||||||
|
/// This is useful for dialects of JSON Schema (e.g. OpenAPI 3.0) that do not support booleans as schemas.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ReplaceBoolSchemas {
|
pub struct ReplaceBoolSchemas {
|
||||||
/// TODO document
|
/// When set to `true`, a schema's `additionalProperties` property will not be changed from a boolean.
|
||||||
pub skip_additional_properties: bool,
|
pub skip_additional_properties: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,25 +141,27 @@ impl Visitor for ReplaceBoolSchemas {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
|
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
|
||||||
if self.skip_additional_properties {
|
if !self.skip_additional_properties {
|
||||||
|
visit_schema_object(self, schema);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(obj) = &mut schema.object {
|
if let Some(obj) = &mut schema.object {
|
||||||
if let Some(ap) = &obj.additional_properties {
|
if let Some(ap) = &obj.additional_properties {
|
||||||
if let Schema::Bool(_) = ap.as_ref() {
|
if let Schema::Bool(_) = ap.as_ref() {
|
||||||
let additional_properties = obj.additional_properties.take();
|
let additional_properties = obj.additional_properties.take();
|
||||||
visit_schema_object(self, schema);
|
visit_schema_object(self, schema);
|
||||||
schema.object().additional_properties = additional_properties;
|
schema.object().additional_properties = additional_properties;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visit_schema_object(self, schema);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// This visitor will restructure JSON Schema objects so that the `$ref` property will never appear alongside any other properties.
|
||||||
|
///
|
||||||
|
/// This is useful for dialects of JSON Schema (e.g. Draft 7) that do not support other properties alongside `$ref`.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RemoveRefSiblings;
|
pub struct RemoveRefSiblings;
|
||||||
|
|
||||||
|
@ -147,10 +184,12 @@ impl Visitor for RemoveRefSiblings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO document
|
/// This visitor will remove the `examples` schema property and (if present) set its first value as the `example` property.
|
||||||
|
///
|
||||||
|
/// This is useful for dialects of JSON Schema (e.g. OpenAPI 3.0) that do not support the `examples` property.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SetSingleExample {
|
pub struct SetSingleExample {
|
||||||
/// TODO document
|
/// When set to `true`, the `examples` property will not be removed, but its first value will still be copied to `example`.
|
||||||
pub retain_examples: bool,
|
pub retain_examples: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue