Add documentation comments, rename Visitor2

This commit is contained in:
Graham Esau 2020-09-24 20:32:35 +01:00
parent 0c02525fb9
commit 460976e765
6 changed files with 92 additions and 42 deletions

View file

@ -14,8 +14,8 @@
- `SchemaSettings` no longer implements `PartialEq`
- `SchemaGenerator::into_definitions()` - this has been superseded by `SchemaGenerator::take_definitions()`
### Changed (**BREAKING CHANGES**):
- Minimum supported rust version is now 1.36.0
### Changed:
- **BREAKING CHANGE** Minimum supported rust version is now 1.36.0
### Fixed:
- **BREAKING CHANGE** unknown items in `#[schemars(...)]` attributes now cause a compilation error (https://github.com/GREsau/schemars/issues/18)

View file

@ -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::schema::*;
use crate::{visit::*, JsonSchema, Map};
@ -29,7 +38,7 @@ pub struct SchemaSettings {
/// Defaults to `"http://json-schema.org/draft-07/schema#"`.
pub meta_schema: Option<String>,
/// 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: (),
}
@ -105,7 +114,7 @@ impl 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
}
@ -225,7 +234,7 @@ impl 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())
}
@ -336,31 +345,31 @@ impl SchemaGenerator {
/// - [`Visitor`]
/// - [`std::fmt::Debug`]
/// - [`std::any::Any`] (implemented for all `'static` types)
/// - [`dyn_clone::DynClone`] (or [`std::clone::Clone`])
/// - [`std::clone::Clone`]
///
/// # Example
/// ```
/// use schemars::visit::Visitor;
/// use schemars::gen::Visitor2;
/// use schemars::gen::GenVisitor;
///
/// #[derive(Debug, Clone)]
/// struct MyVisitor;
///
/// impl Visitor for MyVisitor { }
///
/// let v: &dyn Visitor2 = &MyVisitor;
/// assert_eq!(v.as_any().is::<MyVisitor>(), true);
/// let v: &dyn GenVisitor = &MyVisitor;
/// 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.
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
T: Visitor + Debug + DynClone + Any,
T: Visitor + Debug + Clone + Any,
{
fn as_any(&self) -> &dyn Any {
self

View file

@ -227,7 +227,8 @@ pub type Map<K, V> = indexmap::IndexMap<K, V>;
pub type Set<T> = std::collections::BTreeSet<T>;
/// 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.
#[cfg(not(feature = "preserve_order"))]
pub type MapEntry<'a, K, V> = std::collections::btree_map::Entry<'a, K, V>;
@ -239,11 +240,8 @@ mod json_schema_impls;
#[macro_use]
mod macros;
/// JSON Schema generator and settings.
pub mod gen;
/// JSON Schema types.
pub mod schema;
/// TODO document
pub mod visit;
#[cfg(feature = "schemars_derive")]

View file

@ -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
/// ```

View file

@ -1,3 +1,7 @@
/*!
JSON Schema types.
*/
#[cfg(feature = "impl_json_schema")]
use crate as schemars;
#[cfg(feature = "impl_json_schema")]

View file

@ -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};
/// TODO document
/// Trait used to recursively modify a constructed schema and its subschemas.
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) {
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) {
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) {
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) {
v.visit_schema_object(&mut root.schema);
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) {
if let Schema::Object(schema) = 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) {
if let Some(sub) = &mut schema.subschemas {
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)]
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,
}
@ -106,25 +141,27 @@ impl Visitor for ReplaceBoolSchemas {
}
fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
if self.skip_additional_properties {
if let Some(obj) = &mut schema.object {
if let Some(ap) = &obj.additional_properties {
if let Schema::Bool(_) = ap.as_ref() {
let additional_properties = obj.additional_properties.take();
visit_schema_object(self, schema);
schema.object().additional_properties = additional_properties;
if !self.skip_additional_properties {
visit_schema_object(self, schema);
return;
}
return;
}
if let Some(obj) = &mut schema.object {
if let Some(ap) = &obj.additional_properties {
if let Schema::Bool(_) = ap.as_ref() {
let additional_properties = obj.additional_properties.take();
visit_schema_object(self, schema);
schema.object().additional_properties = additional_properties;
}
}
}
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)]
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)]
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,
}