Add separate docs for v0.8/v1

This commit is contained in:
Graham Esau 2024-06-09 19:01:24 +01:00
parent 3150f98fc8
commit d511d447f7
61 changed files with 1620 additions and 58 deletions

View file

@ -1,5 +1,4 @@
---
layout: default
title: Deriving JsonSchema
nav_order: 2
has_children: true
@ -12,6 +11,7 @@ permalink: /deriving/
The most important trait in Schemars is `JsonSchema`, and the most important function of that trait is `json_schema(...)` which returns a JSON schema describing the type. Implementing this manually on many types would be slow and error-prone, so Schemars includes a derive macro which can implement that trait for you. Any derived implementation of `JsonSchema` should create a schema that describes the JSON representation of the type if it were to be serialized by serde_json.
Usually, all you need to do to use it is to add a `#[derive(JsonSchema)]` attribute to your type:
```rust
use schemars::{JsonSchema, schema_for};
@ -28,7 +28,8 @@ fn main() {
println!("{}", serialized);
}
```
<!-- TODO:
<!-- TODO:
show example output
requirements - when can/can't it be derived
generic params behaviour

View file

@ -1,5 +1,4 @@
---
layout: default
title: Attributes
parent: Deriving JsonSchema
nav_order: 1
@ -26,30 +25,31 @@ TABLE OF CONTENTS
</summary>
1. [Supported Serde Attributes](#supported-serde-attributes)
- [`rename`](#rename)
- [`rename_all`](#rename_all)
- [`tag` / `content` / `untagged`](#tag)
- [`default`](#default)
- [`skip`](#skip)
- [`skip_serializing`](#skip_serializing)
- [`skip_deserializing`](#skip_deserializing)
- [`flatten`](#flatten)
- [`with`](#with)
- [`bound`](#bound)
- [`rename`](#rename)
- [`rename_all`](#rename_all)
- [`tag` / `content` / `untagged`](#tag)
- [`default`](#default)
- [`skip`](#skip)
- [`skip_serializing`](#skip_serializing)
- [`skip_deserializing`](#skip_deserializing)
- [`flatten`](#flatten)
- [`with`](#with)
- [`bound`](#bound)
1. [Supported Validator Attributes](#supported-validator-attributes)
- [`email` / `phone` / `url`](#email-phone-url)
- [`length`](#length)
- [`range`](#range)
- [`regex`](#regex)
- [`contains`](#contains)
- [`required` / `required_nested`](#required)
- [`email` / `phone` / `url`](#email-phone-url)
- [`length`](#length)
- [`range`](#range)
- [`regex`](#regex)
- [`contains`](#contains)
- [`required` / `required_nested`](#required)
1. [Other Attributes](#other-attributes)
- [`schema_with`](#schema_with)
- [`title` / `description`](#title-description)
- [`example`](#example)
- [`deprecated`](#deprecated)
- [`crate`](#crate)
- [Doc Comments (`doc`)](#doc)
- [`schema_with`](#schema_with)
- [`title` / `description`](#title-description)
- [`example`](#example)
- [`deprecated`](#deprecated)
- [`crate`](#crate)
- [Doc Comments (`doc`)](#doc)
</details>
## Supported Serde Attributes
@ -59,6 +59,7 @@ TABLE OF CONTENTS
<h3 id="rename">
`#[serde(rename = "name")]` / `#[schemars(rename = "name")]`
</h3>
Set on a struct, enum, field or variant to use the given name in the generated schema instead of the Rust name. When used on a struct or enum, the given name will be used as the title for root schemas, and the key within the root's `definitions` property for subschemas.
@ -70,6 +71,7 @@ Serde docs: [container](https://serde.rs/container-attrs.html#rename) / [variant
<h3 id="rename_all">
`#[serde(rename_all = "...")]` / `#[schemars(rename_all = "...")]`
</h3>
Set on a struct, enum or variant to rename all fields according to the given case convention (see the Serde docs for details).
@ -81,6 +83,7 @@ Serde docs: [container](https://serde.rs/container-attrs.html#rename_all) / [var
`#[serde(tag = "type")]` / `#[schemars(tag = "type")]` <br />
`#[serde(tag = "t", content = "c")]` / `#[schemars(tag = "t", content = "c")]` <br />
`#[serde(untagged)]` / `#[schemars(untagged)]`
</h3>
Set on an enum to generate the schema for the [internally tagged](https://serde.rs/enum-representations.html#internally-tagged), [adjacently tagged](https://serde.rs/enum-representations.html#adjacently-tagged), or [untagged](https://serde.rs/enum-representations.html#untagged) representation of this enum.
@ -90,6 +93,7 @@ Serde docs: [`tag`](https://serde.rs/container-attrs.html#tag) / [`tag`+`content
<h3 id="default">
`#[serde(default)]` / `#[schemars(default)]` / `#[serde(default = "path")]` / `#[schemars(default = "path")]`
</h3>
Set on a struct or field to give fields a default value, which excludes them from the schema's `required` properties. The default will also be set on the field's schema's `default` property, unless it is skipped by a [`skip_serializing_if`](https://serde.rs/field-attrs.html#skip_serializing_if) attribute on the field. Any [`serialize_with`](https://serde.rs/field-attrs.html#serialize_with) or [`with`](https://serde.rs/field-attrs.html#with) attribute set on the field will be used to serialize the default value.
@ -99,6 +103,7 @@ Serde docs: [container](https://serde.rs/container-attrs.html#default) / [field]
<h3 id="skip">
`#[serde(skip)]` / `#[schemars(skip)]`
</h3>
Set on a variant or field to prevent it from appearing in any generated schema.
@ -108,6 +113,7 @@ Serde docs: [variant](https://serde.rs/variant-attrs.html#skip) / [field](https:
<h3 id="skip_serializing">
`#[serde(skip_serializing)]` / `#[schemars(skip_serializing)]`
</h3>
Set on a field of a (non-tuple) struct to set the `writeOnly` property on that field's schema. Serde also allows this attribute on variants or tuple struct fields, but this will have no effect on generated schemas.
@ -117,6 +123,7 @@ Serde docs: [field](https://serde.rs/field-attrs.html#skip_deserializing)
<h3 id="skip_deserializing">
`#[serde(skip_deserializing)]` / `#[schemars(skip_deserializing)]`
</h3>
Set on a variant or field. When set on a field of a (non-tuple) struct, that field's schema will have the `readOnly` property set. When set on a variant or tuple struct field Schemars will treat this the same as a [`skip`](#skip) attribute.
@ -126,6 +133,7 @@ Serde docs: [variant](https://serde.rs/variant-attrs.html#skip_deserializing) /
<h3 id="flatten">
`#[serde(flatten)]` / `#[schemars(flatten)]`
</h3>
Set on a field to include that field's contents as though they belonged to the field's container.
@ -135,6 +143,7 @@ Serde docs: [field](https://serde.rs/field-attrs.html#flatten)
<h3 id="with">
`#[serde(with = "Type")]` / `#[schemars(with = "Type")]`
</h3>
Set on a variant or field to generate its schema as the given type instead of its actual type. Serde allows the `with` attribute to refer to any module path, but Schemars requires this to be an actual type which implements `JsonSchema`.
@ -146,6 +155,7 @@ Serde docs: [variant](https://serde.rs/variant-attrs.html#with) / [field](https:
<h3 id="deny_unknown_fields">
`#[serde(deny_unknown_fields)]` / `#[schemars(deny_unknown_fields)]`
</h3>
Setting this on a container will set the `additionalProperties` keyword on generated schemas to `false` to show that any extra properties are explicitly disallowed.
@ -155,6 +165,7 @@ Serde docs: [container](https://serde.rs/container-attrs.html#deny_unknown_field
<h3 id="transparent">
`#[serde(transparent)]` / `#[schemars(transparent)]`
</h3>
Set on a newtype struct or a braced struct with one field to make the struct's generated schema exactly the same as that of the single field's.
@ -164,6 +175,7 @@ Serde docs: [container](https://serde.rs/container-attrs.html#transparent)
<h3 id="bound">
`#[schemars(bound = "...")]`
</h3>
Where-clause for the JsonSchema impl. This replaces any trait bounds inferred by schemars. Schemars does **not** use trait bounds from `#[serde(bound)]` attributes.
@ -181,6 +193,7 @@ Serde docs: [container](https://serde.rs/container-attrs.html#bound)
`#[validate(email)]` / `#[schemars(email)]`<br />
`#[validate(phone)]` / `#[schemars(phone)]`<br />
`#[validate(url)]` / `#[schemars(url)]`
</h3>
Sets the schema's `format` to `email`/`phone`/`uri`, as appropriate. Only one of these attributes may be present on a single field.
@ -191,6 +204,7 @@ Validator docs: [email](https://github.com/Keats/validator#email) / [phone](http
`#[validate(length(min = 1, max = 10))]` / `#[schemars(length(min = 1, max = 10))]`<br />
`#[validate(length(equal = 10))]` / `#[schemars(length(equal = 10))]`
</h3>
Sets the `minLength`/`maxLength` properties for string schemas, or the `minItems`/`maxItems` properties for array schemas.
@ -200,6 +214,7 @@ Validator docs: [length](https://github.com/Keats/validator#length)
<h3 id="range">
`#[validate(range(min = 1, max = 10))]` / `#[schemars(range(min = 1, max = 10))]`
</h3>
Sets the `minimum`/`maximum` properties for number schemas.
@ -210,6 +225,7 @@ Validator docs: [range](https://github.com/Keats/validator#range)
`#[validate(regex = "path::to::regex")]` / `#[schemars(regex = "path::to::regex")]`<br />
`#[schemars(regex(pattern = r"^\d+$"))]`
</h3>
Sets the `pattern` property for string schemas. The `path::to::regex` will typically refer to a [`Regex`](https://docs.rs/regex/*/regex/struct.Regex.html) instance, but Schemars allows it to be any value with a `to_string()` method.
@ -221,6 +237,7 @@ Validator docs: [regex](https://github.com/Keats/validator#regex)
<h3 id="contains">
`#[validate(contains = "string")]` / `#[schemars(contains = "string")]`
</h3>
For string schemas, sets the `pattern` property to the given value, with any regex special characters escaped. For object schemas (e.g. when the attribute is set on a HashMap field), includes the value in the `required` property, indicating that the map must contain it as a key.
@ -231,6 +248,7 @@ Validator docs: [contains](https://github.com/Keats/validator#contains)
`#[validate(required)]` / `#[schemars(required)]`<br />
`#[validate(required_nested)]`
</h3>
When set on an `Option<T>` field, this will create a schemas as though the field were a `T`.
@ -244,6 +262,7 @@ Validator docs: [required](https://github.com/Keats/validator#required) / [requi
<h3 id="schema_with">
`#[schemars(schema_with = "some::function")]`
</h3>
Set on a variant or field to generate this field's schema using the given function. This function must be callable as `fn(&mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema`.
@ -251,6 +270,7 @@ Set on a variant or field to generate this field's schema using the given functi
<h3 id="title-description">
`#[schemars(title = "Some title", description = "Some description")]`
</h3>
Set on a container, variant or field to set the generated schema's `title` and/or `description`. If present, these will be used instead of values from any [`doc` comments/attributes](#doc).
@ -258,6 +278,7 @@ Set on a container, variant or field to set the generated schema's `title` and/o
<h3 id="example">
`#[schemars(example = "some::function")]`
</h3>
Set on a container, variant or field to include the result of the given function in the generated schema's `examples`. The function should take no parameters and can return any type that implements serde's `Serialize` trait - it does not need to return the same type as the attached struct/field. This attribute can be repeated to specify multiple examples.
@ -265,6 +286,7 @@ Set on a container, variant or field to include the result of the given function
<h3 id="deprecated">
`#[deprecated]`
</h3>
Set the Rust built-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/an-attribute-for-deprecation.html) attribute on a struct, enum, field or variant to set the generated schema's `deprecated` keyword to `true`.
@ -272,6 +294,7 @@ Set the Rust built-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rus
<h3 id="crate">
`#[schemars(crate = "other_crate::schemars")]`
</h3>
Set the path to the schemars crate instance the generated code should depend on. This is mostly useful for other crates that depend on schemars in their macros.
@ -279,6 +302,7 @@ Set the path to the schemars crate instance the generated code should depend on.
<h3 id="inner">
`#[schemars(inner(...))]`
</h3>
Sets properties specified by [validator attributes](#supported-validator-attributes) on items of an array schema. For example:
@ -293,6 +317,7 @@ struct Struct {
<h3 id="doc">
Doc Comments (`#[doc = "..."]`)
</h3>
If a struct, variant or field has any [doc comments](https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html#doc-comments) (or [`doc` attributes](https://doc.rust-lang.org/rustdoc/the-doc-attribute.html)), then these will be used as the generated schema's `description`. If the first line is an ATX-style markdown heading (i.e. it begins with a # character), then it will be used as the schema's `title`, and the remaining lines will be the `description`.

View file

@ -1,5 +1,4 @@
---
layout: default
title: Implementing JsonSchema
nav_order: 3
permalink: /implementing/

View file

@ -1,5 +1,4 @@
---
layout: default
title: Generating Schemas
nav_order: 4
permalink: /generating/
@ -8,6 +7,7 @@ permalink: /generating/
# Generating Schemas
The easiest way to generate a schema for a type that implements is to use the [`schema_for!` macro](https://docs.rs/schemars/latest/schemars/macro.schema_for.html), like so:
```rust
let my_schema = schema_for!(MyStruct);
```
@ -15,8 +15,9 @@ let my_schema = schema_for!(MyStruct);
This will create a schema that conforms to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
If you want more control over how the schema is generated, you can use the [`gen` module](https://docs.rs/schemars/latest/schemars/gen/). There are two main types in this module:
* [`SchemaSettings`](https://docs.rs/schemars/latest/schemars/gen/struct.SchemaSettings.html), which defines what JSON Schema features should be used when generating schemas (for example, how `Option`s should be represented).
* [`SchemaGenerator`](https://docs.rs/schemars/latest/schemars/gen/struct.SchemaGenerator.html), which manages the generation of a schema document.
- [`SchemaSettings`](https://docs.rs/schemars/latest/schemars/gen/struct.SchemaSettings.html), which defines what JSON Schema features should be used when generating schemas (for example, how `Option`s should be represented).
- [`SchemaGenerator`](https://docs.rs/schemars/latest/schemars/gen/struct.SchemaGenerator.html), which manages the generation of a schema document.
See the API documentation for more info on how to use those types for custom schema generation.

View file

@ -1,5 +1,4 @@
---
layout: default
title: Feature Flags
nav_order: 5
permalink: /features/

View file

@ -1,9 +1,8 @@
---
layout: default
title: Examples
nav_order: 6
has_children: true
permalink: /examples/
---
# Examples
# Examples

14
docs/Dockerfile Normal file
View file

@ -0,0 +1,14 @@
FROM ruby:2.7.4
EXPOSE 4000
RUN gem update --system 3.4.22 && echo 'url: "http://localhost:4000"' > /_config.localhost.yml
COPY Gemfile .
RUN bundle install
ENV JEKYLL_ENV=docker
ENTRYPOINT [ "bundle", "exec", "jekyll"]
CMD [ "serve", "--force_polling", "--host", "0.0.0.0", "--config", "./_config.yml,/_config.localhost.yml" ]

View file

@ -10,7 +10,7 @@ source "https://rubygems.org"
# gem "jekyll", "~> 4.0.0"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
# gem "minima", "~> 2.5"
gem "just-the-docs", "= 0.3.2"
gem "just-the-docs", "= 0.8.2"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
gem "github-pages", group: :jekyll_plugins

View file

@ -27,20 +27,47 @@ url: "https://graham.cool" # the base hostname & protocol for your site, e.g. ht
permalink: pretty
# Build settings
remote_theme: pmarsceill/just-the-docs@v0.3.2
remote_theme: pmarsceill/just-the-docs@v0.8.2
markdown: CommonMarkGhPages
commonmark:
options: ["UNSAFE", "FOOTNOTES"]
color_scheme: default
aux_links:
'<img src="https://img.shields.io/badge/GitHub--lightgrey?style=social&amp;logo=github" alt="Schemars on GitHub" title="Schemars on GitHub">':
- "https://github.com/GREsau/schemars"
'<img src="https://img.shields.io/badge/API%20documentation--lightgrey?style=social" alt="Schemars API docs" title="Schemars API docs">':
- "https://docs.rs/schemars"
'<img src="https://img.shields.io/crates/v/schemars?style=social" alt="Schemars on crates.io" title="Schemars on crates.io">':
- "https://crates.io/crates/schemars"
'<img src="https://img.shields.io/badge/GitHub--lightgrey?style=social&amp;logo=github" alt="Schemars on GitHub" title="Schemars on GitHub">':
- "https://github.com/GREsau/schemars"
'<img src="https://img.shields.io/badge/API%20documentation--lightgrey?style=social" alt="Schemars API docs" title="Schemars API docs">':
- "https://docs.rs/schemars"
'<img src="https://img.shields.io/crates/v/schemars?style=social" alt="Schemars on crates.io" title="Schemars on crates.io">':
- "https://crates.io/crates/schemars"
collections:
v0:
permalink: "/:collection/:path/"
output: true
just_the_docs:
collections:
v0:
name: v0.8
nav_fold: true
defaults:
- scope:
path: ""
type: v0
values:
layout: v0
- scope:
path: ""
values:
layout: v1
callouts_level: quiet
callouts:
info:
color: blue
opacity: 0.1
# Exclude from processing.
# The following items will not be processed, by default.
# Any item listed under the `exclude:` key here will be automatically added to

View file

@ -0,0 +1,14 @@
{% capture input %}examples/{{ include.name }}.rs{% endcapture %}
{% capture output %}examples/{{ include.name }}.schema.json{% endcapture %}
```rust
{% include {{ input }} %}
```
<details>
<summary>Click to see the output JSON schema...</summary>
```json
{% include {{ output }} -%}
```
</details>

View file

@ -0,0 +1,60 @@
use schemars::schema::{Schema, SchemaObject};
use schemars::{gen::SchemaGenerator, schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
// `int_as_string` and `bool_as_string` use the schema for `String`.
#[derive(Default, Deserialize, Serialize, JsonSchema)]
pub struct MyStruct {
#[serde(default = "eight", with = "as_string")]
#[schemars(with = "String")]
pub int_as_string: i32,
#[serde(default = "eight")]
pub int_normal: i32,
#[serde(default, with = "as_string")]
#[schemars(schema_with = "make_custom_schema")]
pub bool_as_string: bool,
#[serde(default)]
pub bool_normal: bool,
}
fn make_custom_schema(gen: &mut SchemaGenerator) -> Schema {
let mut schema: SchemaObject = <String>::json_schema(gen).into();
schema.format = Some("boolean".to_owned());
schema.into()
}
fn eight() -> i32 {
8
}
// This module serializes values as strings
mod as_string {
use serde::{de::Error, Deserialize, Deserializer, Serializer};
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: std::fmt::Display,
S: Serializer,
{
serializer.collect_str(value)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: std::str::FromStr,
D: Deserializer<'de>,
{
let string = String::deserialize(deserializer)?;
string
.parse()
.map_err(|_| D::Error::custom("Input was not valid"))
}
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,25 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"properties": {
"bool_as_string": {
"default": "false",
"type": "string",
"format": "boolean"
},
"bool_normal": {
"default": false,
"type": "boolean"
},
"int_as_string": {
"default": "8",
"type": "string"
},
"int_normal": {
"default": 8,
"type": "integer",
"format": "int32"
}
}
}

View file

@ -0,0 +1,24 @@
use schemars::{gen::SchemaSettings, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let settings = SchemaSettings::draft07().with(|s| {
s.option_nullable = true;
s.option_add_null_type = false;
});
let gen = settings.into_generator();
let schema = gen.into_root_schema_for::<MyStruct>();
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,68 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"my_bool",
"my_int"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"allOf": [
{
"$ref": "#/definitions/MyEnum"
}
],
"nullable": true
}
},
"definitions": {
"MyEnum": {
"oneOf": [
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}

View file

@ -0,0 +1,33 @@
use schemars::{schema_for, JsonSchema};
/// # My Amazing Struct
/// This struct shows off generating a schema with
/// a custom title and description.
#[derive(JsonSchema)]
pub struct MyStruct {
/// # My Amazing Integer
pub my_int: i32,
/// This bool has a description, but no title.
pub my_bool: bool,
/// # A Nullable Enum
/// This enum might be set, or it might not.
pub my_nullable_enum: Option<MyEnum>,
}
/// # My Amazing Enum
#[derive(JsonSchema)]
pub enum MyEnum {
/// A wrapper around a `String`
StringNewType(String),
/// A struct-like enum variant which contains
/// some floats
StructVariant {
/// The floats themselves
floats: Vec<f32>,
},
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,79 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "My Amazing Struct",
"description": "This struct shows off generating a schema with a custom title and description.",
"type": "object",
"required": [
"my_bool",
"my_int"
],
"properties": {
"my_bool": {
"description": "This bool has a description, but no title.",
"type": "boolean"
},
"my_int": {
"title": "My Amazing Integer",
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"title": "A Nullable Enum",
"description": "This enum might be set, or it might not.",
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
}
},
"definitions": {
"MyEnum": {
"title": "My Amazing Enum",
"oneOf": [
{
"description": "A wrapper around a `String`",
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"description": "A struct-like enum variant which contains some floats",
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"description": "The floats themselves",
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}

View file

@ -0,0 +1,15 @@
use schemars::{schema_for, JsonSchema_repr};
#[derive(JsonSchema_repr)]
#[repr(u8)]
enum SmallPrime {
Two = 2,
Three = 3,
Five = 5,
Seven = 7,
}
fn main() {
let schema = schema_for!(SmallPrime);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,11 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "SmallPrime",
"type": "integer",
"enum": [
2,
3,
5,
7
]
}

View file

@ -0,0 +1,24 @@
use schemars::schema_for_value;
use serde::Serialize;
#[derive(Serialize)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Serialize)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let schema = schema_for_value!(MyStruct {
my_int: 123,
my_bool: true,
my_nullable_enum: Some(MyEnum::StringNewType("foo".to_string()))
});
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,23 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"examples": [
{
"my_bool": true,
"my_int": 123,
"my_nullable_enum": {
"StringNewType": "foo"
}
}
],
"type": "object",
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer"
},
"my_nullable_enum": true
}
}

View file

@ -0,0 +1,19 @@
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
pub my_int: i32,
pub my_bool: bool,
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,70 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"my_bool",
"my_int"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32"
},
"my_nullable_enum": {
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
}
},
"definitions": {
"MyEnum": {
"oneOf": [
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
},
"additionalProperties": false
}
]
}
}
}

View file

@ -0,0 +1,42 @@
// Pretend that this is somebody else's crate, not a module.
mod other_crate {
// Neither Schemars nor the other crate provides a JsonSchema impl
// for this struct.
pub struct Duration {
pub secs: i64,
pub nanos: i32,
}
}
////////////////////////////////////////////////////////////////////////////////
use other_crate::Duration;
use schemars::{schema_for, JsonSchema};
// This is just a copy of the remote data structure that Schemars can use to
// create a suitable JsonSchema impl.
#[derive(JsonSchema)]
#[serde(remote = "Duration")]
pub struct DurationDef {
pub secs: i64,
pub nanos: i32,
}
// Now the remote type can be used almost like it had its own JsonSchema impl
// all along. The `with` attribute gives the path to the definition for the
// remote type. Note that the real type of the field is the remote type, not
// the definition type.
#[derive(JsonSchema)]
pub struct Process {
pub command_line: String,
#[serde(with = "DurationDef")]
pub wall_time: Duration,
// Generic types must be explicitly specified with turbofix `::<>` syntax.
#[serde(with = "Vec::<DurationDef>")]
pub durations: Vec<Duration>,
}
fn main() {
let schema = schema_for!(Process);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,43 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Process",
"type": "object",
"required": [
"command_line",
"durations",
"wall_time"
],
"properties": {
"command_line": {
"type": "string"
},
"durations": {
"type": "array",
"items": {
"$ref": "#/definitions/Duration"
}
},
"wall_time": {
"$ref": "#/definitions/Duration"
}
},
"definitions": {
"Duration": {
"type": "object",
"required": [
"nanos",
"secs"
],
"properties": {
"nanos": {
"type": "integer",
"format": "int32"
},
"secs": {
"type": "integer",
"format": "int64"
}
}
}
}
}

View file

@ -0,0 +1,30 @@
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
pub struct MyStruct {
#[serde(rename = "thisIsOverridden")]
#[schemars(rename = "myNumber", range(min = 1, max = 10))]
pub my_int: i32,
pub my_bool: bool,
#[schemars(default)]
pub my_nullable_enum: Option<MyEnum>,
#[schemars(inner(regex(pattern = "^x$")))]
pub my_vec_str: Vec<String>,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[schemars(untagged)]
pub enum MyEnum {
StringNewType(#[schemars(phone)] String),
StructVariant {
#[schemars(length(min = 1, max = 100))]
floats: Vec<f32>,
},
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,67 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"myBool",
"myNumber",
"myVecStr"
],
"properties": {
"myBool": {
"type": "boolean"
},
"myNullableEnum": {
"default": null,
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
},
"myNumber": {
"type": "integer",
"format": "int32",
"maximum": 10.0,
"minimum": 1.0
},
"myVecStr": {
"type": "array",
"items": {
"type": "string",
"pattern": "^x$"
}
}
},
"additionalProperties": false,
"definitions": {
"MyEnum": {
"anyOf": [
{
"type": "string",
"format": "phone"
},
{
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
},
"maxItems": 100,
"minItems": 1
}
}
}
]
}
}
}

View file

@ -0,0 +1,24 @@
use schemars::{schema_for, JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct MyStruct {
#[serde(rename = "myNumber")]
pub my_int: i32,
pub my_bool: bool,
#[serde(default)]
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(untagged)]
pub enum MyEnum {
StringNewType(String),
StructVariant { floats: Vec<f32> },
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,54 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"myBool",
"myNumber"
],
"properties": {
"myBool": {
"type": "boolean"
},
"myNullableEnum": {
"default": null,
"anyOf": [
{
"$ref": "#/definitions/MyEnum"
},
{
"type": "null"
}
]
},
"myNumber": {
"type": "integer",
"format": "int32"
}
},
"additionalProperties": false,
"definitions": {
"MyEnum": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
}
}
}
}
]
}
}
}

View file

@ -0,0 +1,24 @@
use schemars::{schema_for, JsonSchema};
#[derive(JsonSchema)]
pub struct MyStruct {
#[validate(range(min = 1, max = 10))]
pub my_int: i32,
pub my_bool: bool,
#[validate(required)]
pub my_nullable_enum: Option<MyEnum>,
}
#[derive(JsonSchema)]
pub enum MyEnum {
StringNewType(#[validate(phone)] String),
StructVariant {
#[validate(length(min = 1, max = 100))]
floats: Vec<f32>,
},
}
fn main() {
let schema = schema_for!(MyStruct);
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

View file

@ -0,0 +1,64 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "MyStruct",
"type": "object",
"required": [
"my_bool",
"my_int",
"my_nullable_enum"
],
"properties": {
"my_bool": {
"type": "boolean"
},
"my_int": {
"type": "integer",
"format": "int32",
"maximum": 10.0,
"minimum": 1.0
},
"my_nullable_enum": {
"oneOf": [
{
"type": "object",
"required": [
"StringNewType"
],
"properties": {
"StringNewType": {
"type": "string",
"format": "phone"
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"StructVariant"
],
"properties": {
"StructVariant": {
"type": "object",
"required": [
"floats"
],
"properties": {
"floats": {
"type": "array",
"items": {
"type": "number",
"format": "float"
},
"maxItems": 100,
"minItems": 1
}
}
}
},
"additionalProperties": false
}
]
}
}
}

10
docs/_layouts/v0.md Normal file
View file

@ -0,0 +1,10 @@
---
layout: default
---
<blockquote class="info">
<p>This page is for the current stable release of Schemars (v0.8.x).
<p>To view this page for the v1 version of Schemars, which is still under development, <a href="{{ page.url | remove_first: "/v0" | relative_url }}">click here</a>.
</blockquote>
{{ content }}

10
docs/_layouts/v1.md Normal file
View file

@ -0,0 +1,10 @@
---
layout: default
---
<blockquote class="info">
<p>This page is for the current v1 alpha version of Schemars. This version is still under development, and further breaking changes may be introduced.
<p>To view this page for the current stable release of Schemars (v0.8.x), <a href="{{ page.url | prepend: "/v0" | relative_url }}">click here</a>.
</blockquote>
{{ content }}

View file

@ -4,7 +4,7 @@ $body-text-color: $grey-dk-200;
$nav-child-link-color: $link-color;
$content-width: 900px;
$content-width: 60rem;
$media-queries: (
xs: 320px,

View file

@ -16,10 +16,10 @@ code {
}
// Always expand nav menu items
.nav-list .nav-list-item > .nav-list {
.nav-list:not(.nav-category-list) .nav-list-item > .nav-list {
display: block;
}
.nav-list-expander {
.nav-list:not(.nav-category-list) .nav-list-expander {
display: none;
}

36
docs/_v0/1-deriving.md Normal file
View file

@ -0,0 +1,36 @@
---
title: Deriving JsonSchema
nav_order: 2
has_children: true
has_toc: false
permalink: /v0/deriving/
---
# Deriving JsonSchema
The most important trait in Schemars is `JsonSchema`, and the most important function of that trait is `json_schema(...)` which returns a JSON schema describing the type. Implementing this manually on many types would be slow and error-prone, so Schemars includes a derive macro which can implement that trait for you. Any derived implementation of `JsonSchema` should create a schema that describes the JSON representation of the type if it were to be serialized by serde_json.
Usually, all you need to do to use it is to add a `#[derive(JsonSchema)]` attribute to your type:
```rust
use schemars::{JsonSchema, schema_for};
#[derive(JsonSchema, Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let schema = schema_for!(Point);
let serialized = serde_json::to_string(&schema).unwrap();
println!("{}", serialized);
}
```
<!-- TODO:
show example output
requirements - when can/can't it be derived
generic params behaviour
-->

323
docs/_v0/1.1-attributes.md Normal file
View file

@ -0,0 +1,323 @@
---
title: Attributes
parent: Deriving JsonSchema
nav_order: 1
permalink: /v0/deriving/attributes/
---
<style>
h3 code {
font-weight: bold;
}
</style>
# Attributes
You can add attributes to your types to customize Schemars's derived `JsonSchema` implementation.
[Serde](https://serde.rs/) allows setting `#[serde(...)]` attributes which change how types are serialized, and Schemars will generally respect these attributes to ensure that generated schemas will match how the type is serialized by serde_json. `#[serde(...)]` attributes can be overriden using `#[schemars(...)]` attributes, which behave identically (e.g. `#[schemars(rename_all = "camelCase")]`). You may find this useful if you want to change the generated schema without affecting Serde's behaviour, or if you're just not using Serde.
[Validator](https://github.com/Keats/validator) allows setting `#[validate(...)]` attributes to restrict valid values of particular fields, many of which will be used by Schemars to generate more accurate schemas. These can also be overridden by `#[schemars(...)]` attributes.
<details open>
<summary style="font-weight: bold">
TABLE OF CONTENTS
</summary>
1. [Supported Serde Attributes](#supported-serde-attributes)
- [`rename`](#rename)
- [`rename_all`](#rename_all)
- [`tag` / `content` / `untagged`](#tag)
- [`default`](#default)
- [`skip`](#skip)
- [`skip_serializing`](#skip_serializing)
- [`skip_deserializing`](#skip_deserializing)
- [`flatten`](#flatten)
- [`with`](#with)
- [`bound`](#bound)
1. [Supported Validator Attributes](#supported-validator-attributes)
- [`email` / `phone` / `url`](#email-phone-url)
- [`length`](#length)
- [`range`](#range)
- [`regex`](#regex)
- [`contains`](#contains)
- [`required` / `required_nested`](#required)
1. [Other Attributes](#other-attributes)
- [`schema_with`](#schema_with)
- [`title` / `description`](#title-description)
- [`example`](#example)
- [`deprecated`](#deprecated)
- [`crate`](#crate)
- [Doc Comments (`doc`)](#doc)
</details>
## Supported Serde Attributes
<div class="indented">
<h3 id="rename">
`#[serde(rename = "name")]` / `#[schemars(rename = "name")]`
</h3>
Set on a struct, enum, field or variant to use the given name in the generated schema instead of the Rust name. When used on a struct or enum, the given name will be used as the title for root schemas, and the key within the root's `definitions` property for subschemas.
If set on a struct or enum with generic type parameters, then the given name may contain them enclosed in curly braces (e.g. `{T}`) and they will be replaced with the concrete type names when the schema is generated.
Serde docs: [container](https://serde.rs/container-attrs.html#rename) / [variant](https://serde.rs/variant-attrs.html#rename) / [field](https://serde.rs/field-attrs.html#rename)
<h3 id="rename_all">
`#[serde(rename_all = "...")]` / `#[schemars(rename_all = "...")]`
</h3>
Set on a struct, enum or variant to rename all fields according to the given case convention (see the Serde docs for details).
Serde docs: [container](https://serde.rs/container-attrs.html#rename_all) / [variant](https://serde.rs/variant-attrs.html#rename_all)
<h3 id="tag" style="line-height: 1.5">
`#[serde(tag = "type")]` / `#[schemars(tag = "type")]` <br />
`#[serde(tag = "t", content = "c")]` / `#[schemars(tag = "t", content = "c")]` <br />
`#[serde(untagged)]` / `#[schemars(untagged)]`
</h3>
Set on an enum to generate the schema for the [internally tagged](https://serde.rs/enum-representations.html#internally-tagged), [adjacently tagged](https://serde.rs/enum-representations.html#adjacently-tagged), or [untagged](https://serde.rs/enum-representations.html#untagged) representation of this enum.
Serde docs: [`tag`](https://serde.rs/container-attrs.html#tag) / [`tag`+`content`](https://serde.rs/container-attrs.html#tag--content) / [`untagged`](https://serde.rs/container-attrs.html#untagged)
<h3 id="default">
`#[serde(default)]` / `#[schemars(default)]` / `#[serde(default = "path")]` / `#[schemars(default = "path")]`
</h3>
Set on a struct or field to give fields a default value, which excludes them from the schema's `required` properties. The default will also be set on the field's schema's `default` property, unless it is skipped by a [`skip_serializing_if`](https://serde.rs/field-attrs.html#skip_serializing_if) attribute on the field. Any [`serialize_with`](https://serde.rs/field-attrs.html#serialize_with) or [`with`](https://serde.rs/field-attrs.html#with) attribute set on the field will be used to serialize the default value.
Serde docs: [container](https://serde.rs/container-attrs.html#default) / [field](https://serde.rs/field-attrs.html#default)
<h3 id="skip">
`#[serde(skip)]` / `#[schemars(skip)]`
</h3>
Set on a variant or field to prevent it from appearing in any generated schema.
Serde docs: [variant](https://serde.rs/variant-attrs.html#skip) / [field](https://serde.rs/field-attrs.html#skip)
<h3 id="skip_serializing">
`#[serde(skip_serializing)]` / `#[schemars(skip_serializing)]`
</h3>
Set on a field of a (non-tuple) struct to set the `writeOnly` property on that field's schema. Serde also allows this attribute on variants or tuple struct fields, but this will have no effect on generated schemas.
Serde docs: [field](https://serde.rs/field-attrs.html#skip_deserializing)
<h3 id="skip_deserializing">
`#[serde(skip_deserializing)]` / `#[schemars(skip_deserializing)]`
</h3>
Set on a variant or field. When set on a field of a (non-tuple) struct, that field's schema will have the `readOnly` property set. When set on a variant or tuple struct field Schemars will treat this the same as a [`skip`](#skip) attribute.
Serde docs: [variant](https://serde.rs/variant-attrs.html#skip_deserializing) / [field](https://serde.rs/field-attrs.html#skip_deserializing)
<h3 id="flatten">
`#[serde(flatten)]` / `#[schemars(flatten)]`
</h3>
Set on a field to include that field's contents as though they belonged to the field's container.
Serde docs: [field](https://serde.rs/field-attrs.html#flatten)
<h3 id="with">
`#[serde(with = "Type")]` / `#[schemars(with = "Type")]`
</h3>
Set on a variant or field to generate its schema as the given type instead of its actual type. Serde allows the `with` attribute to refer to any module path, but Schemars requires this to be an actual type which implements `JsonSchema`.
If the given type has any required generic type parameters, then they must all be explicitly specified in this attribute. Serde frequently allows you to omit them as it can make use of type inference, but unfortunately this is not possible with Schemars. For example, `with = "Vec::<i32>"` will work, but `with = "Vec"` and `with = "Vec::<_>"` will not.
Serde docs: [variant](https://serde.rs/variant-attrs.html#with) / [field](https://serde.rs/field-attrs.html#with)
<h3 id="deny_unknown_fields">
`#[serde(deny_unknown_fields)]` / `#[schemars(deny_unknown_fields)]`
</h3>
Setting this on a container will set the `additionalProperties` keyword on generated schemas to `false` to show that any extra properties are explicitly disallowed.
Serde docs: [container](https://serde.rs/container-attrs.html#deny_unknown_fields)
<h3 id="transparent">
`#[serde(transparent)]` / `#[schemars(transparent)]`
</h3>
Set on a newtype struct or a braced struct with one field to make the struct's generated schema exactly the same as that of the single field's.
Serde docs: [container](https://serde.rs/container-attrs.html#transparent)
<h3 id="bound">
`#[schemars(bound = "...")]`
</h3>
Where-clause for the JsonSchema impl. This replaces any trait bounds inferred by schemars. Schemars does **not** use trait bounds from `#[serde(bound)]` attributes.
Serde docs: [container](https://serde.rs/container-attrs.html#bound)
</div>
## Supported Validator Attributes
<div class="indented">
<h3 id="email-phone-url">
`#[validate(email)]` / `#[schemars(email)]`<br />
`#[validate(phone)]` / `#[schemars(phone)]`<br />
`#[validate(url)]` / `#[schemars(url)]`
</h3>
Sets the schema's `format` to `email`/`phone`/`uri`, as appropriate. Only one of these attributes may be present on a single field.
Validator docs: [email](https://github.com/Keats/validator#email) / [phone](https://github.com/Keats/validator#phone) / [url](https://github.com/Keats/validator#url)
<h3 id="length">
`#[validate(length(min = 1, max = 10))]` / `#[schemars(length(min = 1, max = 10))]`<br />
`#[validate(length(equal = 10))]` / `#[schemars(length(equal = 10))]`
</h3>
Sets the `minLength`/`maxLength` properties for string schemas, or the `minItems`/`maxItems` properties for array schemas.
Validator docs: [length](https://github.com/Keats/validator#length)
<h3 id="range">
`#[validate(range(min = 1, max = 10))]` / `#[schemars(range(min = 1, max = 10))]`
</h3>
Sets the `minimum`/`maximum` properties for number schemas.
Validator docs: [range](https://github.com/Keats/validator#range)
<h3 id="regex">
`#[validate(regex = "path::to::regex")]` / `#[schemars(regex = "path::to::regex")]`<br />
`#[schemars(regex(pattern = r"^\d+$"))]`
</h3>
Sets the `pattern` property for string schemas. The `path::to::regex` will typically refer to a [`Regex`](https://docs.rs/regex/*/regex/struct.Regex.html) instance, but Schemars allows it to be any value with a `to_string()` method.
Providing an inline regex pattern using `regex(pattern = ...)` is a Schemars extension, and not currently supported by the Validator crate. When using this form, you may want to use a `r"raw string literal"` so that `\\` characters in the regex pattern are not interpreted as escape sequences in the string.
Validator docs: [regex](https://github.com/Keats/validator#regex)
<h3 id="contains">
`#[validate(contains = "string")]` / `#[schemars(contains = "string")]`
</h3>
For string schemas, sets the `pattern` property to the given value, with any regex special characters escaped. For object schemas (e.g. when the attribute is set on a HashMap field), includes the value in the `required` property, indicating that the map must contain it as a key.
Validator docs: [contains](https://github.com/Keats/validator#contains)
<h3 id="required">
`#[validate(required)]` / `#[schemars(required)]`<br />
`#[validate(required_nested)]`
</h3>
When set on an `Option<T>` field, this will create a schemas as though the field were a `T`.
Validator docs: [required](https://github.com/Keats/validator#required) / [required_nested](https://github.com/Keats/validator#required_nested)
</div>
## Other Attributes
<h3 id="schema_with">
`#[schemars(schema_with = "some::function")]`
</h3>
Set on a variant or field to generate this field's schema using the given function. This function must be callable as `fn(&mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema`.
<h3 id="title-description">
`#[schemars(title = "Some title", description = "Some description")]`
</h3>
Set on a container, variant or field to set the generated schema's `title` and/or `description`. If present, these will be used instead of values from any [`doc` comments/attributes](#doc).
<h3 id="example">
`#[schemars(example = "some::function")]`
</h3>
Set on a container, variant or field to include the result of the given function in the generated schema's `examples`. The function should take no parameters and can return any type that implements serde's `Serialize` trait - it does not need to return the same type as the attached struct/field. This attribute can be repeated to specify multiple examples.
<h3 id="deprecated">
`#[deprecated]`
</h3>
Set the Rust built-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/an-attribute-for-deprecation.html) attribute on a struct, enum, field or variant to set the generated schema's `deprecated` keyword to `true`.
<h3 id="crate">
`#[schemars(crate = "other_crate::schemars")]`
</h3>
Set the path to the schemars crate instance the generated code should depend on. This is mostly useful for other crates that depend on schemars in their macros.
<h3 id="inner">
`#[schemars(inner(...))]`
</h3>
Sets properties specified by [validator attributes](#supported-validator-attributes) on items of an array schema. For example:
```rs
struct Struct {
#[schemars(inner(url, regex(pattern = "^https://")))]
urls: Vec<String>,
}
```
<h3 id="doc">
Doc Comments (`#[doc = "..."]`)
</h3>
If a struct, variant or field has any [doc comments](https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html#doc-comments) (or [`doc` attributes](https://doc.rust-lang.org/rustdoc/the-doc-attribute.html)), then these will be used as the generated schema's `description`. If the first line is an ATX-style markdown heading (i.e. it begins with a # character), then it will be used as the schema's `title`, and the remaining lines will be the `description`.

View file

@ -0,0 +1,78 @@
---
title: Implementing JsonSchema
nav_order: 3
permalink: /v0/implementing/
---
# Implementing JsonSchema
[Deriving `JsonSchema`]({{ site.baseurl }}{% link 1-deriving.md %}) is usually the easiest way to enable JSON schema generation for your types. But if you need more customisation, you can also implement `JsonSchema` manually. This trait has two associated functions which must be implemented, and one which can optionally be implemented:
## schema_name
```rust
fn schema_name() -> String;
```
This function returns the human-readable friendly name of the type's schema, which frequently is just the name of the type itself. The schema name is used as the title for root schemas, and the key within the root's `definitions` property for subschemas.
NB in a future version of schemars, it's likely that this function will be changed to return a `Cow<'static, str>`.
## schema_id
```rust
fn schema_id() -> Cow<'static, str>;
```
This function returns a unique identifier of the type's schema - if two types return the same `schema_id`, then Schemars will consider them identical types. Because of this, if a type takes any generic type parameters, then its ID should depend on the type arguments. For example, the implementation of this function for `Vec<T> where T: JsonSchema` is:
```rust
fn schema_id() -> Cow<'static, str> {
Cow::Owned(
format!("[{}]", T::schema_id()))
}
```
`&mut Vec<&T>`, `LinkedList<T>`, `Mutex<LinkedList<Arc<T>>>`, and similar collection types also use that implementation, since they produce identical JSON schemas so they can be considered the same type.
For a type with no generic type arguments, a reasonable implementation of this function would be to return the type name including module path (in case there is a type with the same name in another module/crate), e.g.:
```rust
impl JsonSchema for NonGenericType {
fn schema_name() -> String {
// Exclude the module path to make the name in generated schemas clearer.
"NonGenericType".to_owned()
}
fn schema_id() -> Cow<'static, str> {
// Include the module, in case a type with the same name is in another module/crate
Cow::Borrowed(concat!(module_path!(), "::NonGenericType"))
}
fn json_schema(_gen: &mut SchemaGenerator) -> Schema {
todo!()
}
}
```
## json_schema
```rust
fn json_schema(gen: &mut gen::SchemaGenerator) -> Schema;
```
This function creates the JSON schema itself. The `gen` argument can be used to check the schema generation settings, or to get schemas for other types. If you do need schemas for other types, you should call the `gen.subschema_for::<T>()` method instead of `<T>::json_schema(gen)`, as `subschema_for` can add `T`'s schema to the root schema's `definitions` so that it does not need to be duplicated when used more than once.
`json_schema` should not return a `$ref` schema.
## is_referenceable (optional)
```rust
fn is_referenceable() -> bool;
```
If this function returns `true`, then Schemars can re-use the generate schema where possible by adding it to the root schema's `definitions` and having other schemas reference it using the `$ref` keyword. This can greatly simplify schemas that include a particular type multiple times, especially if that type's schema is fairly complex.
Generally, this should return `false` for types with simple schemas (such as primitives). For more complex types, it should return `true`. For recursive types, this **must** return `true` to prevent infinite cycles when generating schemas.
The default implementation of this function returns `true` to reduce the chance of someone inadvertently causing infinite cycles with recursive types.

35
docs/_v0/3-generating.md Normal file
View file

@ -0,0 +1,35 @@
---
title: Generating Schemas
nav_order: 4
permalink: /v0/generating/
---
# Generating Schemas
The easiest way to generate a schema for a type that implements is to use the [`schema_for!` macro](https://docs.rs/schemars/latest/schemars/macro.schema_for.html), like so:
```rust
let my_schema = schema_for!(MyStruct);
```
This will create a schema that conforms to [JSON Schema Draft 7](https://json-schema.org/specification-links.html#draft-7), but this is liable to change in a future version of Schemars if support for other JSON Schema versions is added.
If you want more control over how the schema is generated, you can use the [`gen` module](https://docs.rs/schemars/latest/schemars/gen/). There are two main types in this module:
- [`SchemaSettings`](https://docs.rs/schemars/latest/schemars/gen/struct.SchemaSettings.html), which defines what JSON Schema features should be used when generating schemas (for example, how `Option`s should be represented).
- [`SchemaGenerator`](https://docs.rs/schemars/latest/schemars/gen/struct.SchemaGenerator.html), which manages the generation of a schema document.
See the API documentation for more info on how to use those types for custom schema generation.
## Schema from Example Value
If you want a schema for a type that can't/doesn't implement `JsonSchema`, but does implement `serde::Serialize`, then you can generate a JSON schema from a value of that type using the [`schema_for_value!` macro](https://docs.rs/schemars/latest/schemars/macro.schema_for_value.html). However, this schema will generally be less precise than if the type implemented `JsonSchema` - particularly when it involves enums, since schemars will not make any assumptions about the structure of an enum based on a single variant.
```rust
let value = MyStruct { foo = 123 };
let my_schema = schema_for_value!(value);
```
<!-- TODO:
create and link to example
-->

39
docs/_v0/4-features.md Normal file
View file

@ -0,0 +1,39 @@
---
title: Feature Flags
nav_order: 5
permalink: /v0/features/
---
# Feature Flags and Optional Dependencies
- `derive` (enabled by default) - provides `#[derive(JsonSchema)]` macro
- `impl_json_schema` - implements `JsonSchema` for Schemars types themselves
- `preserve_order` - keep the order of struct fields in `Schema` and `SchemaObject`
- `raw_value` - implements `JsonSchema` for `serde_json::value::RawValue` (enables the serde_json `raw_value` feature)
Schemars can implement `JsonSchema` on types from several popular crates, enabled via feature flags (dependency versions are shown in brackets):
- `chrono` - [chrono](https://crates.io/crates/chrono) (^0.4)
- `indexmap1` - [indexmap](https://crates.io/crates/indexmap) (^1.2)
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
- `either` - [either](https://crates.io/crates/either) (^1.3)
- `uuid08` - [uuid](https://crates.io/crates/uuid) (^0.8)
- `uuid1` - [uuid](https://crates.io/crates/uuid) (^1.0)
- `smallvec` - [smallvec](https://crates.io/crates/smallvec) (^1.0)
- `arrayvec05` - [arrayvec](https://crates.io/crates/arrayvec) (^0.5)
- `arrayvec07` - [arrayvec](https://crates.io/crates/arrayvec) (^0.7)
- `url` - [url](https://crates.io/crates/url) (^2.0)
- `bytes` - [bytes](https://crates.io/crates/bytes) (^1.0)
- `enumset` - [enumset](https://crates.io/crates/enumset) (^1.0)
- `rust_decimal` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
- `bigdecimal03` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.3)
- `bigdecimal04` - [bigdecimal](https://crates.io/crates/bigdecimal) (^0.4)
- `smol_str` - [smol_str](https://crates.io/crates/smol_str) (^0.1.17)
- `semver` - [semver](https://crates.io/crates/semver) (^1.0.9)
For example, to implement `JsonSchema` on types from `chrono`, enable it as a feature in the `schemars` dependency in your `Cargo.toml` like so:
```toml
[dependencies]
schemars = { version = "0.8", features = ["chrono"] }
```

8
docs/_v0/5-examples.md Normal file
View file

@ -0,0 +1,8 @@
---
title: Examples
nav_order: 6
has_children: true
permalink: /v0/examples/
---
# Examples

View file

@ -0,0 +1,12 @@
---
title: Deriving JsonSchema
parent: Examples
nav_order: 1
summary: Deriving JsonSchema on a struct and enum.
---
# Deriving JsonSchema
This is the simplest usage of Schemars. Both types are made to derive `JsonSchema`, and the `schema_for!` macro is used to generate the schema itself.
{% include example_v0.md name="main" %}

View file

@ -0,0 +1,14 @@
---
title: Using Serde Attributes
parent: Examples
nav_order: 2
summary: "Deriving JsonSchema on types that use #[serde] attributes to customise serialization behaviour."
---
# Using Serde Attributes
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema _should_ match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
The list of supported `#[serde]` attributes are [documented here]({{ site.baseurl }}{% link 1.1-attributes.md %}#supported-serde-attributes).
{% include example_v0.md name="serde_attrs" %}

View file

@ -0,0 +1,12 @@
---
title: Using Schemars Attributes
parent: Examples
nav_order: 3
summary: "Deriving JsonSchema on types that use #[schemars] attributes to customise serialization behaviour."
---
# Using Serde Attributes
`#[serde(...)]` attributes can be overriden (or replaced) with `#[schemars(...)]` attributes, which behave identically. You may find this useful if you want to change the generated schema without affecting Serde's behaviour, or if you're just not using Serde.
{% include example_v0.md name="schemars_attrs" %}

View file

@ -0,0 +1,12 @@
---
title: Custom Schema Settings
parent: Examples
nav_order: 4
summary: Generating a schema using custom settings which changes how Option<T> is handled.
---
# Custom Schema Settings
The `gen` module allows you to customise how schemas are generated. For example, the default behaviour for `Option<T>` is to include `null` in the schema's `type`s, but we can instead add a `nullable` property to its schema:
{% include example_v0.md name="custom_settings" %}

View file

@ -0,0 +1,16 @@
---
title: Derive for Remote Crate
parent: Examples
nav_order: 5
summary: Deriving JsonSchema implementations for a type in somebody else's crate.
---
# Deriving JsonSchema for a Type in a Different Crate
Rust's [orphan rule](https://doc.rust-lang.org/book/traits.html#rules-for-implementing-traits) requires that either the trait or the type for which you are implementing the trait must be defined in the same crate as the impl, so it is not possible to implement `JsonSchema` for a type in a different crate directly.
To work around this, Schemars provides a way of deriving `JsonSchema` implementations for types in other people's crates. The only catch is that you have to provide a definition of the type for Schemars's derive to process.
This is the same way that Serde allows remote deriving, which is why this page reads so similarly to [Serde's documentation](https://serde.rs/remote-derive.html)!
{% include example_v0.md name="remote_derive" %}

View file

@ -0,0 +1,12 @@
---
title: Doc Comments
parent: Examples
nav_order: 6
summary: Giving schemas a custom title and/or description using doc comments.
---
# Setting a Custom Title and/or Description Using Doc Comments
If a struct, variant or field has any [doc comments](https://doc.rust-lang.org/stable/rust-by-example/meta/doc.html#doc-comments) (or [`doc` attributes](https://doc.rust-lang.org/rustdoc/the-doc-attribute.html)), then these will be used as the generated schema's `description`. If the first line is an ATX-style markdown heading (i.e. it begins with a # character), then it will be used as the schema's `title`, and the remaining lines will be the `description`.
{% include example_v0.md name="doc_comments" %}

View file

@ -0,0 +1,19 @@
---
title: Custom Serialization
parent: Examples
nav_order: 7
summary: >-
If a field has a #[serde(with = "path")] attribute where "path" is not a type that implements JsonSchema,
then in order to derive JsonSchema on the type, it must also have a #[schemars(with = "Type")] attribute,
where "Type" implements JsonSchema.
---
# Deriving JsonSchema with Fields Using Custom Serialization
Serde allows you to change how a field is (de)serialized by setting a [`#[serde(with = "path")]`](https://serde.rs/field-attrs.html#with) attribute, where `$path::serialize` and `$path::deserialize` must be functions with the correct signature. Schemars supports the same attribute, but `path` must be a type implementing `JsonSchema`.
In order to derive `JsonSchema` on a type which includes a `#[serde(with = "path")]` attribute where `path` is not a type implementing `JsonSchema`, you'll need to override it with a suitable `#[schemars(with = "Type")]` or `#[schemars(schema_with = "path")]` attribute.
{% include example_v0.md name="custom_serialization" %}
Note that the `default` values in the schema are serialized as strings where appropriate.

View file

@ -0,0 +1,13 @@
---
title: Serialize Enum as Number (serde_repr)
parent: Examples
nav_order: 8
summary: >-
Generating a schema for with a C-like enum compatible with serde_repr.
---
# Serialize Enum as Number (serde_repr Compatibility)
If you use the `#[repr(...)]` attribute on an enum to give it a C-like representation, then you may also want to use the [serde_repr](https://github.com/dtolnay/serde-repr) crate to serialize the enum values as numbers. In this case, you should use the corresponding `JsonSchema_repr` derive to ensure the schema for your type reflects how serde formats your type.
{% include example_v0.md name="enum_repr" %}

View file

@ -0,0 +1,15 @@
---
title: Generate Schema from Example Value
parent: Examples
nav_order: 9
summary: >-
Generating a schema for a serializable value.
---
# Generate Schema from Example Value
If you want a schema for a type that can't/doesn't implement `JsonSchema`, but does implement [`serde::Serialize`](https://docs.serde.rs/serde/trait.Serialize.html), then you can generate a JSON schema from a value of that type. However, this schema will generally be less precise than if the type implemented `JsonSchema` - particularly when it involves enums, since schemars will not make any assumptions about the structure of an enum based on a single variant.
{% include example_v0.md name="from_value" %}
Note that the schema for the enum is not very useful in this case, since schemars doesn't know anything about the second variant.

20
docs/_v0/index.md Normal file
View file

@ -0,0 +1,20 @@
---
title: Overview
has_children: true
nav_order: 1
permalink: /v0/
---
# Schemars
Schemars is a library to generate JSON Schema documents from Rust data structures.
This is built on Rust's trait system - any type which implements the [`JsonSchema`](https://docs.rs/schemars/latest/schemars/trait.JsonSchema.html) trait can have a JSON Schema generated describing that type. Schemars implements this on many standard library types, and provides a derive macro to automatically implement it on custom types.
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema _should_ match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
## Basic Usage
If you don't really care about the specifics, the easiest way to generate a JSON schema for your types is to `#[derive(JsonSchema)]` and use the `schema_for!` macro. All fields of the type must also implement `JsonSchema` - Schemars implements this for many standard library types.
{% include example.md name="main" %}

10
docs/docker-compose.yml Normal file
View file

@ -0,0 +1,10 @@
---
services:
jekyll:
build:
context: .
volumes:
- ".:/docs"
working_dir: "/docs"
ports:
- 4000:4000

View file

@ -1,5 +1,4 @@
---
layout: default
title: Deriving JsonSchema
parent: Examples
nav_order: 1

View file

@ -1,14 +1,13 @@
---
layout: default
title: Using Serde Attributes
parent: Examples
nav_order: 2
summary: 'Deriving JsonSchema on types that use #[serde] attributes to customise serialization behaviour.'
summary: "Deriving JsonSchema on types that use #[serde] attributes to customise serialization behaviour."
---
# Using Serde Attributes
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema *should* match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema _should_ match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
The list of supported `#[serde]` attributes are [documented here]({{ site.baseurl }}{% link 1.1-attributes.md %}#supported-serde-attributes).

View file

@ -1,9 +1,8 @@
---
layout: default
title: Using Schemars Attributes
parent: Examples
nav_order: 3
summary: 'Deriving JsonSchema on types that use #[schemars] attributes to customise serialization behaviour.'
summary: "Deriving JsonSchema on types that use #[schemars] attributes to customise serialization behaviour."
---
# Using Serde Attributes

View file

@ -1,5 +1,4 @@
---
layout: default
title: Custom Schema Settings
parent: Examples
nav_order: 4

View file

@ -1,5 +1,4 @@
---
layout: default
title: Derive for Remote Crate
parent: Examples
nav_order: 5

View file

@ -1,5 +1,4 @@
---
layout: default
title: Doc Comments
parent: Examples
nav_order: 6

View file

@ -1,5 +1,4 @@
---
layout: default
title: Custom Serialization
parent: Examples
nav_order: 7
@ -13,7 +12,7 @@ summary: >-
Serde allows you to change how a field is (de)serialized by setting a [`#[serde(with = "path")]`](https://serde.rs/field-attrs.html#with) attribute, where `$path::serialize` and `$path::deserialize` must be functions with the correct signature. Schemars supports the same attribute, but `path` must be a type implementing `JsonSchema`.
In order to derive `JsonSchema` on a type which includes a `#[serde(with = "path")]` attribute where `path` is not a type implementing `JsonSchema`, you'll need to override it with a suitable `#[schemars(with = "Type")]` or `#[schemars(schema_with = "path")]` attribute.
In order to derive `JsonSchema` on a type which includes a `#[serde(with = "path")]` attribute where `path` is not a type implementing `JsonSchema`, you'll need to override it with a suitable `#[schemars(with = "Type")]` or `#[schemars(schema_with = "path")]` attribute.
{% include example.md name="custom_serialization" %}

View file

@ -1,5 +1,4 @@
---
layout: default
title: Serialize Enum as Number (serde_repr)
parent: Examples
nav_order: 8

View file

@ -1,5 +1,4 @@
---
layout: default
title: Generate Schema from Example Value
parent: Examples
nav_order: 9

View file

@ -1,5 +1,4 @@
---
layout: default
title: Overview
nav_order: 1
---
@ -10,7 +9,7 @@ Schemars is a library to generate JSON Schema documents from Rust data structure
This is built on Rust's trait system - any type which implements the [`JsonSchema`](https://docs.rs/schemars/latest/schemars/trait.JsonSchema.html) trait can have a JSON Schema generated describing that type. Schemars implements this on many standard library types, and provides a derive macro to automatically implement it on custom types.
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema *should* match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
One of the main aims of this library is compatibility with [Serde](https://github.com/serde-rs/serde). Any generated schema _should_ match how [serde_json](https://github.com/serde-rs/json) would serialize/deserialize to/from JSON. To support this, Schemars will check for any `#[serde(...)]` attributes on types that derive `JsonSchema`, and adjust the generated schema accordingly.
## Basic Usage