Update doc comments and make SchemaGenerator
available from crate root
This commit is contained in:
parent
fb6e1a5c61
commit
760403e2f5
13 changed files with 150 additions and 74 deletions
38
README.md
38
README.md
|
@ -36,10 +36,9 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"title": "MyStruct",
|
"title": "MyStruct",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["my_bool", "my_int"],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"my_bool": {
|
"my_bool": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
@ -51,7 +50,7 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
"my_nullable_enum": {
|
"my_nullable_enum": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/MyEnum"
|
"$ref": "#/$defs/MyEnum"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "null"
|
"type": "null"
|
||||||
|
@ -59,26 +58,25 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"required": ["my_int", "my_bool"],
|
||||||
|
"$defs": {
|
||||||
"MyEnum": {
|
"MyEnum": {
|
||||||
"anyOf": [
|
"oneOf": [
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["StringNewType"],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"StringNewType": {
|
"StringNewType": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false,
|
||||||
|
"required": ["StringNewType"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["StructVariant"],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"StructVariant": {
|
"StructVariant": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["floats"],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"floats": {
|
"floats": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -87,10 +85,12 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
"format": "float"
|
"format": "float"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"required": ["floats"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false,
|
||||||
|
"required": ["StructVariant"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -134,24 +134,23 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
"title": "MyStruct",
|
"title": "MyStruct",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["myBool", "myNumber"],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"myBool": {
|
"myBool": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"myNullableEnum": {
|
"myNullableEnum": {
|
||||||
"default": null,
|
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
"$ref": "#/definitions/MyEnum"
|
"$ref": "#/$defs/MyEnum"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "null"
|
"type": "null"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"default": null
|
||||||
},
|
},
|
||||||
"myNumber": {
|
"myNumber": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -159,7 +158,8 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"definitions": {
|
"required": ["myNumber", "myBool"],
|
||||||
|
"$defs": {
|
||||||
"MyEnum": {
|
"MyEnum": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
|
@ -167,7 +167,6 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["floats"],
|
|
||||||
"properties": {
|
"properties": {
|
||||||
"floats": {
|
"floats": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -176,7 +175,8 @@ println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
"format": "float"
|
"format": "float"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"required": ["floats"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use schemars::Schema;
|
use schemars::{schema_for, JsonSchema, Schema, SchemaGenerator};
|
||||||
use schemars::{gen::SchemaGenerator, schema_for, JsonSchema};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// `int_as_string` and `bool_as_string` use the schema for `String`.
|
// `int_as_string` and `bool_as_string` use the schema for `String`.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use schemars::Schema;
|
use schemars::{schema_for, JsonSchema, Schema, SchemaGenerator};
|
||||||
use schemars::{gen::SchemaGenerator, schema_for, JsonSchema};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
// `int_as_string` and `bool_as_string` use the schema for `String`.
|
// `int_as_string` and `bool_as_string` use the schema for `String`.
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
use crate::gen::SchemaGenerator;
|
use crate::{JsonSchema, Schema, SchemaGenerator};
|
||||||
use crate::JsonSchema;
|
|
||||||
use crate::Schema;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::json;
|
use serde_json::{json, map::Entry, Map, Value};
|
||||||
use serde_json::map::Entry;
|
|
||||||
use serde_json::Map;
|
|
||||||
use serde_json::Value;
|
|
||||||
|
|
||||||
// Helper for generating schemas for flattened `Option` fields.
|
// Helper for generating schemas for flattened `Option` fields.
|
||||||
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
||||||
|
|
|
@ -12,8 +12,8 @@ use crate::{visit::*, JsonSchema};
|
||||||
use dyn_clone::DynClone;
|
use dyn_clone::DynClone;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::{any::Any, collections::HashSet, fmt::Debug};
|
use std::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
type CowStr = std::borrow::Cow<'static, str>;
|
type CowStr = std::borrow::Cow<'static, str>;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ pub struct SchemaSettings {
|
||||||
///
|
///
|
||||||
/// A single leading `#` and/or single trailing `/` are ignored.
|
/// A single leading `#` and/or single trailing `/` are ignored.
|
||||||
///
|
///
|
||||||
/// Defaults to `/$defs`.
|
/// Defaults to `"/$defs"`.
|
||||||
pub definitions_path: String,
|
pub definitions_path: String,
|
||||||
/// The URI of the meta-schema describing the structure of the generated schemas.
|
/// The URI of the meta-schema describing the structure of the generated schemas.
|
||||||
///
|
///
|
||||||
|
@ -55,6 +55,8 @@ pub struct SchemaSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SchemaSettings {
|
impl Default for SchemaSettings {
|
||||||
|
/// The default settings currently conform to [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
|
||||||
|
/// If you rely on generated schemas conforming to draft 2020-12, consider using the [`SchemaSettings::draft2020_12()`] method.
|
||||||
fn default() -> SchemaSettings {
|
fn default() -> SchemaSettings {
|
||||||
SchemaSettings::draft2020_12()
|
SchemaSettings::draft2020_12()
|
||||||
}
|
}
|
||||||
|
@ -97,7 +99,7 @@ impl SchemaSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates `SchemaSettings` that conform to [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject).
|
/// Creates `SchemaSettings` that conform to [OpenAPI 3.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schema).
|
||||||
pub fn openapi3() -> SchemaSettings {
|
pub fn openapi3() -> SchemaSettings {
|
||||||
SchemaSettings {
|
SchemaSettings {
|
||||||
option_nullable: true,
|
option_nullable: true,
|
||||||
|
@ -153,7 +155,7 @@ impl SchemaSettings {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use schemars::{JsonSchema, gen::SchemaGenerator};
|
/// use schemars::{JsonSchema, SchemaGenerator};
|
||||||
///
|
///
|
||||||
/// #[derive(JsonSchema)]
|
/// #[derive(JsonSchema)]
|
||||||
/// struct MyStruct {
|
/// struct MyStruct {
|
||||||
|
@ -203,7 +205,7 @@ impl SchemaGenerator {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use schemars::gen::SchemaGenerator;
|
/// use schemars::SchemaGenerator;
|
||||||
///
|
///
|
||||||
/// let gen = SchemaGenerator::default();
|
/// let gen = SchemaGenerator::default();
|
||||||
/// let settings = gen.settings();
|
/// let settings = gen.settings();
|
||||||
|
@ -287,7 +289,7 @@ impl SchemaGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the collection of all [non-inlined](JsonSchema::always_inline_schema) schemas that have been generated,
|
/// Returns the collection of all [non-inlined](JsonSchema::always_inline_schema) schemas that have been generated,
|
||||||
/// leaving an empty map in its place.
|
/// leaving an empty `Map` in its place.
|
||||||
///
|
///
|
||||||
/// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
|
/// The keys of the returned `Map` are the [schema names](JsonSchema::schema_name), and the values are the schemas
|
||||||
/// themselves.
|
/// themselves.
|
||||||
|
@ -300,11 +302,10 @@ impl SchemaGenerator {
|
||||||
self.settings.visitors.iter_mut().map(|v| v.as_mut())
|
self.settings.visitors.iter_mut().map(|v| v.as_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a root JSON Schema for the type `T`.
|
/// Generates a JSON Schema for the type `T`.
|
||||||
///
|
///
|
||||||
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
|
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
|
||||||
/// add them to the `SchemaGenerator`'s schema definitions and include them in the returned `SchemaObject`'s
|
/// include them in the returned `Schema` at the [definitions path](SchemaSettings::definitions_path) (by default `"$defs"`).
|
||||||
/// [`definitions`](../schema/struct.Metadata.html#structfield.definitions)
|
|
||||||
pub fn root_schema_for<T: ?Sized + JsonSchema>(&mut self) -> Schema {
|
pub fn root_schema_for<T: ?Sized + JsonSchema>(&mut self) -> Schema {
|
||||||
let mut schema = self.json_schema_internal::<T>(T::schema_id());
|
let mut schema = self.json_schema_internal::<T>(T::schema_id());
|
||||||
|
|
||||||
|
@ -324,10 +325,10 @@ impl SchemaGenerator {
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes `self` and generates a root JSON Schema for the type `T`.
|
/// Consumes `self` and generates a JSON Schema for the type `T`.
|
||||||
///
|
///
|
||||||
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
|
/// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
|
||||||
/// include them in the returned `SchemaObject`'s [`definitions`](../schema/struct.Metadata.html#structfield.definitions)
|
/// include them in the returned `Schema` at the [definitions path](SchemaSettings::definitions_path) (by default `"$defs"`).
|
||||||
pub fn into_root_schema_for<T: ?Sized + JsonSchema>(mut self) -> Schema {
|
pub fn into_root_schema_for<T: ?Sized + JsonSchema>(mut self) -> Schema {
|
||||||
let mut schema = self.json_schema_internal::<T>(T::schema_id());
|
let mut schema = self.json_schema_internal::<T>(T::schema_id());
|
||||||
|
|
||||||
|
@ -348,10 +349,12 @@ impl SchemaGenerator {
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a root JSON Schema for the given example value.
|
/// Generates a JSON Schema for the given example value.
|
||||||
///
|
///
|
||||||
/// If the value implements [`JsonSchema`](crate::JsonSchema), then prefer using the [`root_schema_for()`](Self::root_schema_for())
|
/// If the value implements [`JsonSchema`](crate::JsonSchema), then prefer using the [`root_schema_for()`](Self::root_schema_for())
|
||||||
/// function which will generally produce a more precise schema, particularly when the value contains any enums.
|
/// function which will generally produce a more precise schema, particularly when the value contains any enums.
|
||||||
|
///
|
||||||
|
/// If the `Serialize` implementation of the value decides to fail, this will return an [`Err`].
|
||||||
pub fn root_schema_for_value<T: ?Sized + Serialize>(
|
pub fn root_schema_for_value<T: ?Sized + Serialize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
value: &T,
|
value: &T,
|
||||||
|
@ -377,10 +380,12 @@ impl SchemaGenerator {
|
||||||
Ok(schema)
|
Ok(schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Consumes `self` and generates a root JSON Schema for the given example value.
|
/// Consumes `self` and generates a JSON Schema for the given example value.
|
||||||
///
|
///
|
||||||
/// If the value implements [`JsonSchema`](crate::JsonSchema), then prefer using the [`into_root_schema_for()!`](Self::into_root_schema_for())
|
/// If the value implements [`JsonSchema`](crate::JsonSchema), then prefer using the [`into_root_schema_for()!`](Self::into_root_schema_for())
|
||||||
/// function which will generally produce a more precise schema, particularly when the value contains any enums.
|
/// function which will generally produce a more precise schema, particularly when the value contains any enums.
|
||||||
|
///
|
||||||
|
/// If the `Serialize` implementation of the value decides to fail, this will return an [`Err`].
|
||||||
pub fn into_root_schema_for_value<T: ?Sized + Serialize>(
|
pub fn into_root_schema_for_value<T: ?Sized + Serialize>(
|
||||||
mut self,
|
mut self,
|
||||||
value: &T,
|
value: &T,
|
||||||
|
@ -513,7 +518,7 @@ fn json_pointer_mut<'a>(
|
||||||
Some(object)
|
Some(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [Visitor](Visitor) which implements additional traits required to be included in a [SchemaSettings].
|
/// A [Visitor] which implements additional traits required to be included in a [SchemaSettings].
|
||||||
///
|
///
|
||||||
/// You will rarely need to use this trait directly as it is automatically implemented for any type which implements all of:
|
/// You will rarely need to use this trait directly as it is automatically implemented for any type which implements all of:
|
||||||
/// - [`Visitor`]
|
/// - [`Visitor`]
|
||||||
|
|
|
@ -11,7 +11,9 @@ mod macros;
|
||||||
/// outside of `schemars`, and should not be considered part of the public API.
|
/// outside of `schemars`, and should not be considered part of the public API.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod _private;
|
pub mod _private;
|
||||||
|
/// Types for generating JSON schemas.
|
||||||
pub mod gen;
|
pub mod gen;
|
||||||
|
/// Types for recursively modifying JSON schemas.
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
|
||||||
#[cfg(feature = "schemars_derive")]
|
#[cfg(feature = "schemars_derive")]
|
||||||
|
@ -25,6 +27,7 @@ pub use schemars_derive::*;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use serde_json as _serde_json;
|
pub use serde_json as _serde_json;
|
||||||
|
|
||||||
|
pub use gen::SchemaGenerator;
|
||||||
pub use schema::Schema;
|
pub use schema::Schema;
|
||||||
|
|
||||||
/// A type which can be described as a JSON Schema document.
|
/// A type which can be described as a JSON Schema document.
|
||||||
|
@ -50,7 +53,7 @@ pub use schema::Schema;
|
||||||
/// you will need to determine an appropriate name and ID for the type.
|
/// you will need to determine an appropriate name and ID for the type.
|
||||||
/// For non-generic types, the type name/path are suitable for this:
|
/// For non-generic types, the type name/path are suitable for this:
|
||||||
/// ```
|
/// ```
|
||||||
/// use schemars::{gen::SchemaGenerator, Schema, JsonSchema};
|
/// use schemars::{SchemaGenerator, Schema, JsonSchema, json_schema};
|
||||||
/// use std::borrow::Cow;
|
/// use std::borrow::Cow;
|
||||||
///
|
///
|
||||||
/// struct NonGenericType;
|
/// struct NonGenericType;
|
||||||
|
@ -67,7 +70,9 @@ pub use schema::Schema;
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
|
/// fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
|
||||||
/// todo!()
|
/// json_schema!({
|
||||||
|
/// "foo": "bar"
|
||||||
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -76,7 +81,7 @@ pub use schema::Schema;
|
||||||
///
|
///
|
||||||
/// But generic type parameters which may affect the generated schema should typically be included in the name/ID:
|
/// But generic type parameters which may affect the generated schema should typically be included in the name/ID:
|
||||||
/// ```
|
/// ```
|
||||||
/// use schemars::{gen::SchemaGenerator, Schema, JsonSchema};
|
/// use schemars::{SchemaGenerator, Schema, JsonSchema, json_schema};
|
||||||
/// use std::{borrow::Cow, marker::PhantomData};
|
/// use std::{borrow::Cow, marker::PhantomData};
|
||||||
///
|
///
|
||||||
/// struct GenericType<T>(PhantomData<T>);
|
/// struct GenericType<T>(PhantomData<T>);
|
||||||
|
@ -95,7 +100,9 @@ pub use schema::Schema;
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
|
/// fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
|
||||||
/// todo!()
|
/// json_schema!({
|
||||||
|
/// "foo": "bar"
|
||||||
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -126,7 +133,7 @@ pub trait JsonSchema {
|
||||||
/// If two types produce different schemas, then they **must** have different `schema_id()`s,
|
/// If two types produce different schemas, then they **must** have different `schema_id()`s,
|
||||||
/// but two types that produce identical schemas should *ideally* have the same `schema_id()`.
|
/// but two types that produce identical schemas should *ideally* have the same `schema_id()`.
|
||||||
///
|
///
|
||||||
/// The default implementation returns the same value as `schema_name()`.
|
/// The default implementation returns the same value as [`schema_name()`](JsonSchema::schema_name).
|
||||||
fn schema_id() -> Cow<'static, str> {
|
fn schema_id() -> Cow<'static, str> {
|
||||||
Self::schema_name()
|
Self::schema_name()
|
||||||
}
|
}
|
||||||
|
@ -134,14 +141,14 @@ pub trait JsonSchema {
|
||||||
/// Generates a JSON Schema for this type.
|
/// Generates a JSON Schema for this type.
|
||||||
///
|
///
|
||||||
/// If the returned schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
|
/// If the returned schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then this method will
|
||||||
/// add them to the [`SchemaGenerator`](gen::SchemaGenerator)'s schema definitions.
|
/// add them to the [`SchemaGenerator`](SchemaGenerator)'s schema definitions.
|
||||||
///
|
///
|
||||||
/// This should not return a `$ref` schema.
|
/// This should not return a `$ref` schema.
|
||||||
fn json_schema(gen: &mut gen::SchemaGenerator) -> Schema;
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema;
|
||||||
|
|
||||||
// TODO document and bring into public API?
|
// TODO document and bring into public API?
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn _schemars_private_non_optional_json_schema(gen: &mut gen::SchemaGenerator) -> Schema {
|
fn _schemars_private_non_optional_json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
Self::json_schema(gen)
|
Self::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,12 @@
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! schema_for {
|
macro_rules! schema_for {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$type>()
|
$crate::SchemaGenerator::default().into_root_schema_for::<$type>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a [`RootSchema`](crate::schema::RootSchema) for the given type using default settings.
|
/// Generates a [`Schema`](crate::Schema) for the given type using default settings.
|
||||||
|
/// The default settings currently conform to [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
|
||||||
///
|
///
|
||||||
/// The type must implement [`JsonSchema`](crate::JsonSchema).
|
/// The type must implement [`JsonSchema`](crate::JsonSchema).
|
||||||
///
|
///
|
||||||
|
@ -40,22 +41,23 @@ macro_rules! schema_for {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! schema_for {
|
macro_rules! schema_for {
|
||||||
($type:ty) => {
|
($type:ty) => {
|
||||||
$crate::gen::SchemaGenerator::default().into_root_schema_for::<$type>()
|
$crate::SchemaGenerator::default().into_root_schema_for::<$type>()
|
||||||
};
|
};
|
||||||
($_:expr) => {
|
($_:expr) => {
|
||||||
compile_error!("This argument to `schema_for!` is not a type - did you mean to use `schema_for_value!` instead?")
|
compile_error!("This argument to `schema_for!` is not a type - did you mean to use `schema_for_value!` instead?")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a [`RootSchema`](crate::schema::RootSchema) for the given example value using default settings.
|
/// Generates a [`Schema`](crate::Schema) for the given example value using default settings.
|
||||||
|
/// The default settings currently conform to [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
|
||||||
///
|
///
|
||||||
/// The value must implement [`Serialize`](serde::Serialize). If the value also implements [`JsonSchema`](crate::JsonSchema),
|
/// The value must implement [`Serialize`](serde::Serialize). If the value also implements [`JsonSchema`](crate::JsonSchema),
|
||||||
/// then prefer using the [`schema_for!`](schema_for) macro which will generally produce a more precise schema,
|
/// then prefer using the [`schema_for!(Type)`](schema_for) macro which will generally produce a more precise schema,
|
||||||
/// particularly when the value contains any enums.
|
/// particularly when the value contains any enums.
|
||||||
///
|
///
|
||||||
/// If the `Serialize` implementation of the value decides to fail, this macro will panic.
|
/// If the `Serialize` implementation of the value decides to fail, this macro will panic.
|
||||||
/// For a non-panicking alternative, create a [`SchemaGenerator`](crate::gen::SchemaGenerator) and use
|
/// For a non-panicking alternative, create a [`SchemaGenerator`](crate::SchemaGenerator) and use
|
||||||
/// its [`into_root_schema_for_value`](crate::gen::SchemaGenerator::into_root_schema_for_value) method.
|
/// its [`into_root_schema_for_value`](crate::SchemaGenerator::into_root_schema_for_value) method.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -71,13 +73,26 @@ macro_rules! schema_for {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! schema_for_value {
|
macro_rules! schema_for_value {
|
||||||
($value:expr) => {
|
($value:expr) => {
|
||||||
$crate::gen::SchemaGenerator::default()
|
$crate::SchemaGenerator::default()
|
||||||
.into_root_schema_for_value(&$value)
|
.into_root_schema_for_value(&$value)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO doc
|
/// Construct a [`Schema`](crate::Schema) from a JSON literal. This can either be a JSON object, or a boolean (`true` or `false`).
|
||||||
|
///
|
||||||
|
/// You can interpolate variables or expressions into a JSON object using the same rules as the [`serde_json::json`] macro.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use schemars::{Schema, json_schema};
|
||||||
|
///
|
||||||
|
/// let desc = "A helpful description.";
|
||||||
|
/// let my_schema: Schema = json_schema!({
|
||||||
|
/// "description": desc,
|
||||||
|
/// "type": ["object", "null"]
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! json_schema {
|
macro_rules! json_schema {
|
||||||
(
|
(
|
||||||
|
|
|
@ -7,6 +7,54 @@ use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
/// A JSON Schema.
|
/// A JSON Schema.
|
||||||
|
///
|
||||||
|
/// This wraps a JSON [`Value`] that must be either an [object](Value::Object) or a [bool](Value::Bool).
|
||||||
|
///
|
||||||
|
/// A custom JSON schema can be created using the [`json_schema!`](crate::json_schema) macro:
|
||||||
|
/// ```
|
||||||
|
/// use schemars::{Schema, json_schema};
|
||||||
|
///
|
||||||
|
/// let my_schema: Schema = json_schema!({
|
||||||
|
/// "type": ["object", "null"]
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Because a `Schema` is a thin wrapper around a `Value`, you can also use [`TryFrom::try_from`]/[`TryInto::try_into`] to create a `Schema` from an existing `Value`.
|
||||||
|
/// This operation is fallible, because only [objects](Value::Object) and [bools](Value::Bool) can be converted in this way.
|
||||||
|
/// ```
|
||||||
|
/// use schemars::{Schema, json_schema};
|
||||||
|
/// use serde_json::json;
|
||||||
|
///
|
||||||
|
/// let json_object = json!({"type": ["object", "null"]});
|
||||||
|
/// let object_schema: Schema = json_object.try_into().unwrap();
|
||||||
|
///
|
||||||
|
/// let json_bool = json!(true);
|
||||||
|
/// let bool_schema: Schema = json_bool.try_into().unwrap();
|
||||||
|
///
|
||||||
|
/// let json_string = json!("This is neither an object nor a bool!");
|
||||||
|
/// assert!(Schema::try_from(json_string).is_err());
|
||||||
|
///
|
||||||
|
/// // You can also convert a `&Value`/`&mut Value` to a `&Schema`/`&mut Schema` the same way:
|
||||||
|
///
|
||||||
|
/// let json_object = json!({"type": ["object", "null"]});
|
||||||
|
/// let object_schema_ref: &Schema = (&json_object).try_into().unwrap();
|
||||||
|
///
|
||||||
|
/// let mut json_object = json!({"type": ["object", "null"]});
|
||||||
|
/// let object_schema_mut: &mut Schema = (&mut json_object).try_into().unwrap();
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Similarly, you can use [`From`]/[`Into`] to (infallibly) create a `Schema` from an existing [`Map<String, Value>`] or [`bool`].
|
||||||
|
/// ```
|
||||||
|
/// use schemars::{Schema, json_schema};
|
||||||
|
/// use serde_json::{Map, json};
|
||||||
|
///
|
||||||
|
/// let mut map = Map::new();
|
||||||
|
/// map.insert("type".to_owned(), json!(["object", "null"]));
|
||||||
|
/// let object_schema: Schema = map.into();
|
||||||
|
///
|
||||||
|
/// let bool_schema: Schema = true.into();
|
||||||
|
/// ```
|
||||||
#[derive(Debug, Clone, PartialEq, RefCastCustom)]
|
#[derive(Debug, Clone, PartialEq, RefCastCustom)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Schema(Value);
|
pub struct Schema(Value);
|
||||||
|
@ -32,28 +80,32 @@ impl Serialize for Schema {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Schema {
|
impl Schema {
|
||||||
pub fn new() -> Self {
|
/// Creates a new schema object with a single string property `"$ref"`.
|
||||||
Self(Value::Object(Map::new()))
|
///
|
||||||
}
|
/// The given reference string should be a URI reference. This will usually be a JSON Pointer
|
||||||
|
/// in [URI Fragment representation](https://tools.ietf.org/html/rfc6901#section-6).
|
||||||
pub fn new_ref(reference: String) -> Self {
|
pub fn new_ref(reference: String) -> Self {
|
||||||
let mut map = Map::new();
|
let mut map = Map::new();
|
||||||
map.insert("$ref".to_owned(), Value::String(reference));
|
map.insert("$ref".to_owned(), Value::String(reference));
|
||||||
Self(Value::Object(map))
|
Self(Value::Object(map))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Borrows the `Schema`'s underlying JSON value.
|
||||||
pub fn as_value(&self) -> &Value {
|
pub fn as_value(&self) -> &Value {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the `Schema`'s underlying JSON value is a bool, returns the bool value.
|
||||||
pub fn as_bool(&self) -> Option<bool> {
|
pub fn as_bool(&self) -> Option<bool> {
|
||||||
self.0.as_bool()
|
self.0.as_bool()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the `Schema`'s underlying JSON value is an object, borrows the object as a `Map` of properties.
|
||||||
pub fn as_object(&self) -> Option<&Map<String, Value>> {
|
pub fn as_object(&self) -> Option<&Map<String, Value>> {
|
||||||
self.0.as_object()
|
self.0.as_object()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If the `Schema`'s underlying JSON value is an object, mutably borrows the object as a `Map` of properties.
|
||||||
pub fn as_object_mut(&mut self) -> Option<&mut Map<String, Value>> {
|
pub fn as_object_mut(&mut self) -> Option<&mut Map<String, Value>> {
|
||||||
self.0.as_object_mut()
|
self.0.as_object_mut()
|
||||||
}
|
}
|
||||||
|
@ -66,10 +118,15 @@ impl Schema {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the `Schema`'s underlying JSON value.
|
||||||
pub fn to_value(self) -> Value {
|
pub fn to_value(self) -> Value {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts the `Schema` (if it wraps a bool value) into an equivalent object schema. Then mutably borrows the object as a `Map` of properties.
|
||||||
|
///
|
||||||
|
/// `true` is transformed into an empty schema `{}`, which successfully validates against all possible values.
|
||||||
|
/// `false` is transformed into the schema `{"not": {}}`, which does not successfully validate against any value.
|
||||||
pub fn ensure_object(&mut self) -> &mut Map<String, Value> {
|
pub fn ensure_object(&mut self) -> &mut Map<String, Value> {
|
||||||
if let Some(b) = self.as_bool() {
|
if let Some(b) = self.as_bool() {
|
||||||
let mut map = Map::new();
|
let mut map = Map::new();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::gen::SchemaGenerator;
|
use crate::{json_schema, JsonSchema, Schema, SchemaGenerator};
|
||||||
use crate::{json_schema, JsonSchema, Schema};
|
|
||||||
use serde_json::{Error, Map, Value};
|
use serde_json::{Error, Map, Value};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod util;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
fn schema_fn(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema {
|
fn schema_fn(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
<bool>::json_schema(gen)
|
<bool>::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod util;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
fn schema_fn(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema {
|
fn schema_fn(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
<bool>::json_schema(gen)
|
<bool>::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,11 +68,11 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
|
||||||
<#ty as schemars::JsonSchema>::schema_id()
|
<#ty as schemars::JsonSchema>::schema_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema {
|
fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
<#ty as schemars::JsonSchema>::json_schema(gen)
|
<#ty as schemars::JsonSchema>::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _schemars_private_non_optional_json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema {
|
fn _schemars_private_non_optional_json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(gen)
|
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ fn derive_json_schema(mut input: syn::DeriveInput, repr: bool) -> syn::Result<To
|
||||||
#schema_id
|
#schema_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema {
|
fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
#schema_expr
|
#schema_expr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn type_for_schema(with_attr: &WithAttr) -> (syn::Type, Option<TokenStream>) {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::Schema {
|
fn json_schema(gen: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
#fun(gen)
|
#fun(gen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue