├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── clippy.toml ├── docs-rs-custom.css ├── docs ├── .gitignore ├── 0-migrating.md ├── 1-deriving.md ├── 1.1-attributes.md ├── 2-implementing.md ├── 3-generating.md ├── 4-features.md ├── 404.html ├── 5-examples.md ├── Dockerfile ├── Gemfile ├── _config.yml ├── _includes │ ├── attributes.md │ ├── deriving.md │ ├── example.md │ ├── example_v0.md │ ├── examples │ │ ├── custom_serialization.rs │ │ ├── custom_serialization.schema.json │ │ ├── custom_settings.rs │ │ ├── custom_settings.schema.json │ │ ├── doc_comments.rs │ │ ├── doc_comments.schema.json │ │ ├── enum_repr.rs │ │ ├── enum_repr.schema.json │ │ ├── from_value.rs │ │ ├── from_value.schema.json │ │ ├── main.rs │ │ ├── main.schema.json │ │ ├── remote_derive.rs │ │ ├── remote_derive.schema.json │ │ ├── schemars_attrs.rs │ │ ├── schemars_attrs.schema.json │ │ ├── serde_attrs.rs │ │ ├── serde_attrs.schema.json │ │ ├── serialize_contract.rs │ │ ├── serialize_contract.schema.json │ │ ├── validate.rs │ │ └── validate.schema.json │ └── examples_v0 │ │ ├── custom_serialization.rs │ │ ├── custom_serialization.schema.json │ │ ├── custom_settings.rs │ │ ├── custom_settings.schema.json │ │ ├── doc_comments.rs │ │ ├── doc_comments.schema.json │ │ ├── enum_repr.rs │ │ ├── enum_repr.schema.json │ │ ├── from_value.rs │ │ ├── from_value.schema.json │ │ ├── main.rs │ │ ├── main.schema.json │ │ ├── remote_derive.rs │ │ ├── remote_derive.schema.json │ │ ├── schemars_attrs.rs │ │ ├── schemars_attrs.schema.json │ │ ├── serde_attrs.rs │ │ ├── serde_attrs.schema.json │ │ ├── validate.rs │ │ └── validate.schema.json ├── _layouts │ ├── v0.md │ └── v1.md ├── _sass │ ├── color_schemes │ │ └── default.scss │ └── custom │ │ └── custom.scss ├── _v0 │ ├── 1-deriving.md │ ├── 1.1-attributes.md │ ├── 2-implementing.md │ ├── 3-generating.md │ ├── 4-features.md │ ├── 5-examples.md │ ├── examples │ │ ├── 1-derive_jsonschema.md │ │ ├── 2-serde_attrs.md │ │ ├── 3-schemars_attrs.md │ │ ├── 4-custom_settings.md │ │ ├── 5-remote_derive.md │ │ ├── 6-doc_comments.md │ │ ├── 7-custom_serialization.md │ │ ├── 8-enum_repr.md │ │ └── 9-from_value.md │ └── index.md ├── assets │ └── js │ │ └── zzzz-search-data.json ├── docker-compose.yml ├── examples │ ├── 1-derive_jsonschema.md │ ├── 2-serde_attrs.md │ ├── 3-schemars_attrs.md │ ├── 4-custom_settings.md │ ├── 5-remote_derive.md │ ├── 6-doc_comments.md │ ├── 7-custom_serialization.md │ ├── 8-enum_repr.md │ └── 9-from_value.md └── index.md ├── schemars ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── docs-rs-custom.css ├── examples │ ├── custom_serialization.rs │ ├── custom_serialization.schema.json │ ├── custom_settings.rs │ ├── custom_settings.schema.json │ ├── doc_comments.rs │ ├── doc_comments.schema.json │ ├── enum_repr.rs │ ├── enum_repr.schema.json │ ├── from_value.rs │ ├── from_value.schema.json │ ├── main.rs │ ├── main.schema.json │ ├── remote_derive.rs │ ├── remote_derive.schema.json │ ├── schemars_attrs.rs │ ├── schemars_attrs.schema.json │ ├── serde_attrs.rs │ ├── serde_attrs.schema.json │ ├── serialize_contract.rs │ ├── serialize_contract.schema.json │ ├── validate.rs │ └── validate.schema.json ├── src │ ├── _private │ │ ├── mod.rs │ │ ├── regex_syntax.rs │ │ └── rustdoc.rs │ ├── consts.rs │ ├── generate.rs │ ├── json_schema_impls │ │ ├── array.rs │ │ ├── arrayvec07.rs │ │ ├── atomic.rs │ │ ├── bytes1.rs │ │ ├── chrono04.rs │ │ ├── core.rs │ │ ├── decimal.rs │ │ ├── either1.rs │ │ ├── ffi.rs │ │ ├── indexmap2.rs │ │ ├── jiff02.rs │ │ ├── maps.rs │ │ ├── mod.rs │ │ ├── nonzero.rs │ │ ├── primitives.rs │ │ ├── semver1.rs │ │ ├── sequences.rs │ │ ├── serdejson.rs │ │ ├── std_time.rs │ │ ├── tuple.rs │ │ ├── url2.rs │ │ ├── uuid1.rs │ │ └── wrapper.rs │ ├── lib.rs │ ├── macros.rs │ ├── schema.rs │ ├── ser.rs │ └── transform.rs └── tests │ ├── integration │ ├── arrayvec.rs │ ├── bound.rs │ ├── bytes.rs │ ├── chrono.rs │ ├── contract.rs │ ├── crate_alias.rs │ ├── decimal.rs │ ├── default.rs │ ├── deprecated.rs │ ├── docs.rs │ ├── either.rs │ ├── enum_repr.rs │ ├── enums.rs │ ├── enums_deny_unknown_fields.rs │ ├── enums_flattened.rs │ ├── enums_untagged_variant.rs │ ├── examples.rs │ ├── extend.rs │ ├── flatten.rs │ ├── from_value.rs │ ├── garde.rs │ ├── indexmap.rs │ ├── inline_subschemas.rs │ ├── jiff.rs │ ├── macros.rs │ ├── main.rs │ ├── map.rs │ ├── remote_derive.rs │ ├── same_name.rs │ ├── schema_name.rs │ ├── schema_with.rs │ ├── semver.rs │ ├── settings.rs │ ├── skip.rs │ ├── smallvec.rs │ ├── smol_str.rs │ ├── snapshots │ │ └── schemars │ │ │ └── tests │ │ │ └── integration │ │ │ ├── arrayvec.rs~arrayvec07.json │ │ │ ├── bound.rs~manual_bound_set.json │ │ │ ├── bytes.rs~bytes.de.json │ │ │ ├── bytes.rs~bytes.ser.json │ │ │ ├── chrono.rs~chrono.json │ │ │ ├── contract.rs~adjacently_tagged_enum.de.json │ │ │ ├── contract.rs~adjacently_tagged_enum.ser.json │ │ │ ├── contract.rs~externally_tagged_enum.de.json │ │ │ ├── contract.rs~externally_tagged_enum.ser.json │ │ │ ├── contract.rs~internally_tagged_enum.de.json │ │ │ ├── contract.rs~internally_tagged_enum.ser.json │ │ │ ├── contract.rs~struct_allow_unknown_fields.de.json │ │ │ ├── contract.rs~struct_allow_unknown_fields.ser.json │ │ │ ├── contract.rs~struct_deny_unknown_fields.de.json │ │ │ ├── contract.rs~struct_deny_unknown_fields.ser.json │ │ │ ├── contract.rs~tuple_struct.de.json │ │ │ ├── contract.rs~tuple_struct.ser.json │ │ │ ├── contract.rs~untagged_enum.de.json │ │ │ ├── contract.rs~untagged_enum.ser.json │ │ │ ├── decimal.rs~decimal_types.de.json │ │ │ ├── decimal.rs~decimal_types.ser.json │ │ │ ├── default.rs~default_fields.de.json │ │ │ ├── default.rs~default_fields.ser.json │ │ │ ├── deprecated.rs~deprecated_enum.json │ │ │ ├── deprecated.rs~deprecated_struct.json │ │ │ ├── docs.rs~doc_comments_enum.de.json │ │ │ ├── docs.rs~doc_comments_enum.ser.json │ │ │ ├── docs.rs~doc_comments_override.json │ │ │ ├── docs.rs~doc_comments_struct.json │ │ │ ├── either.rs~either.json │ │ │ ├── enum_repr.rs~enum_repr.json │ │ │ ├── enums.rs~adjacently_tagged_enum.json │ │ │ ├── enums.rs~externally_tagged_enum.json │ │ │ ├── enums.rs~internally_tagged_enum.json │ │ │ ├── enums.rs~no_variants.json │ │ │ ├── enums.rs~renamed.json │ │ │ ├── enums.rs~unit_variants_with_doc_comments.json │ │ │ ├── enums.rs~untagged_enum.json │ │ │ ├── enums.rs~untagged_enum_with_titles.json │ │ │ ├── enums_deny_unknown_fields.rs~adjacently_tagged_enum.json │ │ │ ├── enums_deny_unknown_fields.rs~externally_tagged_enum.json │ │ │ ├── enums_deny_unknown_fields.rs~internally_tagged_enum.json │ │ │ ├── enums_deny_unknown_fields.rs~untagged_enum.json │ │ │ ├── enums_flattened.rs~enums_flattened.json │ │ │ ├── enums_flattened.rs~enums_flattened_deny_unknown_fields.json │ │ │ ├── enums_flattened.rs~enums_flattened_deny_unknown_fields_draft07.json │ │ │ ├── enums_untagged_variant.rs~adjacently_tagged_enum.json │ │ │ ├── enums_untagged_variant.rs~externally_tagged_enum.json │ │ │ ├── enums_untagged_variant.rs~internally_tagged_enum.json │ │ │ ├── examples.rs~examples.de.json │ │ │ ├── examples.rs~examples.ser.json │ │ │ ├── extend.rs~extend_adjacently_tagged_enum.json │ │ │ ├── extend.rs~extend_externally_tagged_enum.json │ │ │ ├── extend.rs~extend_internally_tagged_enum.json │ │ │ ├── extend.rs~extend_struct.json │ │ │ ├── extend.rs~extend_tuple_struct.json │ │ │ ├── extend.rs~extend_untagged_enum.json │ │ │ ├── flatten.rs~flattened_struct.json │ │ │ ├── flatten.rs~flattened_value.json │ │ │ ├── from_value.rs~custom_struct.json │ │ │ ├── from_value.rs~custom_struct_openapi3.json │ │ │ ├── from_value.rs~json_value.json │ │ │ ├── garde.rs~garde_attrs.json │ │ │ ├── garde.rs~garde_attrs_newtype.json │ │ │ ├── garde.rs~garde_attrs_tuple.json │ │ │ ├── inline_subschemas.rs~struct_normal.json │ │ │ ├── inline_subschemas.rs~struct_recursive.de.json │ │ │ ├── inline_subschemas.rs~struct_recursive.ser.json │ │ │ ├── jiff.rs~jiff.json │ │ │ ├── map.rs~maps.json │ │ │ ├── remote_derive.rs~lifetime_param.json │ │ │ ├── remote_derive.rs~simple.json │ │ │ ├── remote_derive.rs~type_param.json │ │ │ ├── same_name.rs~same_name.json │ │ │ ├── schema_with.rs~schema_with.json │ │ │ ├── semver.rs~semver.json │ │ │ ├── settings.rs~draft07.de.json │ │ │ ├── settings.rs~draft07.ser.json │ │ │ ├── settings.rs~draft2019_09.de.json │ │ │ ├── settings.rs~draft2019_09.ser.json │ │ │ ├── settings.rs~draft2020_12.de.json │ │ │ ├── settings.rs~draft2020_12.ser.json │ │ │ ├── settings.rs~openapi3.de.json │ │ │ ├── settings.rs~openapi3.ser.json │ │ │ ├── skip.rs~skip_enum_variants.json │ │ │ ├── skip.rs~skip_struct_field.json │ │ │ ├── structs.rs~deny_unknown_fields.json │ │ │ ├── structs.rs~newtype.json │ │ │ ├── structs.rs~normal.json │ │ │ ├── structs.rs~renamed_fields.json │ │ │ ├── structs.rs~tuple.json │ │ │ ├── structs.rs~unit.json │ │ │ ├── transform.rs~transform_enum.json │ │ │ ├── transform.rs~transform_struct.json │ │ │ ├── transparent.rs~transparent_newtype_with_validation.json │ │ │ ├── transparent.rs~transparent_struct_with_doc.json │ │ │ ├── url.rs~url.json │ │ │ ├── uuid.rs~uuid.json │ │ │ └── validator.rs~validate_attrs.json │ ├── std_types.rs │ ├── structs.rs │ ├── test_helper.rs │ ├── transform.rs │ ├── transparent.rs │ ├── url.rs │ ├── uuid.rs │ └── validator.rs │ ├── ui.rs │ └── ui │ ├── example_fn.rs │ ├── example_fn.stderr │ ├── invalid_attrs.rs │ ├── invalid_attrs.stderr │ ├── invalid_extend.rs │ ├── invalid_extend.stderr │ ├── invalid_validation_attrs.rs │ ├── invalid_validation_attrs.stderr │ ├── repr_missing.rs │ ├── repr_missing.stderr │ ├── repr_non_unit_variant.rs │ ├── repr_non_unit_variant.stderr │ ├── schema_for_arg_value.rs │ ├── schema_for_arg_value.stderr │ ├── transform_str.rs │ └── transform_str.stderr ├── schemars_derive ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── attributes.md ├── deriving.md ├── docs-rs-custom.css └── src │ ├── ast │ ├── from_serde.rs │ └── mod.rs │ ├── attr │ ├── doc.rs │ ├── mod.rs │ ├── parse_meta.rs │ ├── schemars_to_serde.rs │ └── validation.rs │ ├── idents.rs │ ├── lib.rs │ └── schema_exprs.rs ├── update-examples.sh └── update-tests.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | *.json text eol=lf 2 | *.stderr text eol=lf 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: GREsau 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | ci: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | rust: 11 | - 1.74.0 12 | - stable 13 | - beta 14 | - nightly 15 | include: 16 | - rust: 1.74.0 17 | allow_failure: false 18 | - rust: stable 19 | allow_failure: false 20 | - rust: beta 21 | allow_failure: false 22 | - rust: nightly 23 | allow_failure: true 24 | fail-fast: false 25 | steps: 26 | - uses: actions/checkout@v4 27 | - name: Downgrade packages for MSRV 28 | if: matrix.rust == '1.74.0' 29 | run: | 30 | cargo add --dev garde --git https://github.com/jprochazk/garde.git --rev be00ddddf8de14530ee890ccfdbaf0b13fb32852 31 | cargo add --dev validator@0.19 32 | working-directory: ./schemars 33 | - uses: dtolnay/rust-toolchain@master 34 | with: 35 | toolchain: ${{ matrix.rust }} 36 | - name: Check with no feature flags 37 | run: cargo check --verbose --no-default-features 38 | continue-on-error: ${{ matrix.allow_failure }} 39 | working-directory: ./schemars 40 | - name: Run tests 41 | run: cargo test --verbose --all-features --no-fail-fast 42 | continue-on-error: ${{ matrix.allow_failure }} 43 | working-directory: ./schemars 44 | - name: Run derive tests 45 | run: cargo test --verbose --all-features --no-fail-fast 46 | continue-on-error: ${{ matrix.allow_failure }} 47 | working-directory: ./schemars_derive 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.check.command": "clippy", 3 | "rust-analyzer.cargo.features": "all", 4 | "rust-analyzer.testExplorer": true 5 | } 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "schemars", 4 | "schemars_derive" 5 | ] 6 | resolver = "2" 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Graham Esau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /clippy.toml: -------------------------------------------------------------------------------- 1 | doc-valid-idents = ["OpenAPI", "serde_json", ".."] 2 | -------------------------------------------------------------------------------- /docs-rs-custom.css: -------------------------------------------------------------------------------- 1 | /* Hide the `[!NOTE] This branch...` alert at the top of the README, as it's only applicable to users on GitHub */ 2 | h2#schemars + blockquote { 3 | display: none; 4 | } 5 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .sass-cache 3 | .jekyll-cache 4 | .jekyll-metadata 5 | vendor 6 | Gemfile.lock 7 | -------------------------------------------------------------------------------- /docs/1-deriving.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deriving JsonSchema 3 | nav_order: 3 4 | has_children: true 5 | has_toc: false 6 | permalink: /deriving/ 7 | --- 8 | 9 | {% include deriving.md %} 10 | -------------------------------------------------------------------------------- /docs/1.1-attributes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Attributes 3 | parent: Deriving JsonSchema 4 | nav_order: 1 5 | permalink: /deriving/attributes/ 6 | --- 7 | 8 | 14 | 15 | {% include attributes.md %} 16 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /404 3 | layout: default 4 | nav_exclude: true 5 | title: Not Found 6 | --- 7 | 8 | 22 | 23 |
24 |

404

25 | 26 |

Page not found :(

27 |

The requested page could not be found.

28 |
-------------------------------------------------------------------------------- /docs/5-examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Examples 3 | nav_order: 7 4 | has_children: true 5 | permalink: /examples/ 6 | --- 7 | 8 | # Examples 9 | -------------------------------------------------------------------------------- /docs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:2.7.4 2 | 3 | EXPOSE 4000 4 | 5 | RUN gem update --system 3.4.22 && echo 'url: "http://localhost:4000"' > /_config.localhost.yml 6 | 7 | COPY Gemfile . 8 | 9 | RUN bundle install 10 | 11 | ENV JEKYLL_ENV=docker 12 | 13 | ENTRYPOINT [ "bundle", "exec", "jekyll"] 14 | CMD [ "serve", "--force_polling", "--host", "0.0.0.0", "--config", "./_config.yml,/_config.localhost.yml" ] 15 | -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | # Hello! This is where you manage which Jekyll version is used to run. 3 | # When you want to use a different version, change it below, save the 4 | # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: 5 | # 6 | # bundle exec jekyll serve 7 | # 8 | # This will help ensure the proper Jekyll version is running. 9 | # Happy Jekylling! 10 | # gem "jekyll", "~> 4.0.0" 11 | # This is the default theme for new Jekyll sites. You may change this to anything you like. 12 | # gem "minima", "~> 2.5" 13 | gem "just-the-docs", "= 0.9.0" 14 | # If you want to use GitHub Pages, remove the "gem "jekyll"" above and 15 | # uncomment the line below. To upgrade, run `bundle update github-pages`. 16 | gem "github-pages", group: :jekyll_plugins 17 | # If you have any plugins, put them here! 18 | group :jekyll_plugins do 19 | end 20 | 21 | # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem 22 | # and associated library. 23 | install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do 24 | gem "tzinfo", "~> 1.2" 25 | gem "tzinfo-data" 26 | end 27 | -------------------------------------------------------------------------------- /docs/_includes/deriving.md: -------------------------------------------------------------------------------- 1 | # Deriving JsonSchema 2 | 3 | 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. 4 | 5 | Usually, all you need to do to use it is to add a `#[derive(JsonSchema)]` attribute to your type: 6 | 7 | ```rust 8 | use schemars::{JsonSchema, schema_for}; 9 | 10 | #[derive(JsonSchema, Debug)] 11 | struct Point { 12 | x: i32, 13 | y: i32, 14 | } 15 | 16 | fn main() { 17 | let schema = schema_for!(Point); 18 | 19 | let serialized = serde_json::to_string(&schema).unwrap(); 20 | println!("{}", serialized); 21 | } 22 | ``` 23 | 24 | 29 | -------------------------------------------------------------------------------- /docs/_includes/example.md: -------------------------------------------------------------------------------- 1 | {% capture input %}examples/{{ include.name }}.rs{% endcapture %} 2 | {% capture output %}examples/{{ include.name }}.schema.json{% endcapture %} 3 | 4 | ```rust 5 | {% include {{ input }} %} 6 | ``` 7 | 8 |
9 | Click to see the output JSON schema... 10 | 11 | ```json 12 | {% include {{ output }} -%} 13 | ``` 14 |
15 | -------------------------------------------------------------------------------- /docs/_includes/example_v0.md: -------------------------------------------------------------------------------- 1 | {% capture input %}examples_v0/{{ include.name }}.rs{% endcapture %} 2 | {% capture output %}examples_v0/{{ include.name }}.schema.json{% endcapture %} 3 | 4 | ```rust 5 | {% include {{ input }} %} 6 | ``` 7 | 8 |
9 | Click to see the output JSON schema... 10 | 11 | ```json 12 | {% include {{ output }} -%} 13 | ``` 14 | 15 |
16 | -------------------------------------------------------------------------------- /docs/_includes/examples/custom_serialization.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema, Schema, SchemaGenerator}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | // `int_as_string` and `bool_as_string` use the schema for `String`. 5 | #[derive(Default, Deserialize, Serialize, JsonSchema)] 6 | pub struct MyStruct { 7 | #[serde(default = "eight", with = "as_string")] 8 | #[schemars(with = "String")] 9 | pub int_as_string: i32, 10 | 11 | #[serde(default = "eight")] 12 | pub int_normal: i32, 13 | 14 | #[serde(default, with = "as_string")] 15 | #[schemars(schema_with = "make_custom_schema")] 16 | pub bool_as_string: bool, 17 | 18 | #[serde(default)] 19 | pub bool_normal: bool, 20 | } 21 | 22 | fn make_custom_schema(generator: &mut SchemaGenerator) -> Schema { 23 | let mut schema = String::json_schema(generator); 24 | schema.insert("format".into(), "boolean".into()); 25 | schema 26 | } 27 | 28 | fn eight() -> i32 { 29 | 8 30 | } 31 | 32 | // This module serializes values as strings 33 | mod as_string { 34 | use serde::{de::Error, Deserialize, Deserializer, Serializer}; 35 | 36 | pub fn serialize(value: &T, serializer: S) -> Result 37 | where 38 | T: std::fmt::Display, 39 | S: Serializer, 40 | { 41 | serializer.collect_str(value) 42 | } 43 | 44 | pub fn deserialize<'de, T, D>(deserializer: D) -> Result 45 | where 46 | T: std::str::FromStr, 47 | D: Deserializer<'de>, 48 | { 49 | let string = String::deserialize(deserializer)?; 50 | string 51 | .parse() 52 | .map_err(|_| D::Error::custom("Input was not valid")) 53 | } 54 | } 55 | 56 | fn main() { 57 | let schema = schema_for!(MyStruct); 58 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 59 | } 60 | -------------------------------------------------------------------------------- /docs/_includes/examples/custom_serialization.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "bool_as_string": { 7 | "type": "string", 8 | "format": "boolean", 9 | "default": "false" 10 | }, 11 | "bool_normal": { 12 | "type": "boolean", 13 | "default": false 14 | }, 15 | "int_as_string": { 16 | "type": "string", 17 | "default": "8" 18 | }, 19 | "int_normal": { 20 | "type": "integer", 21 | "format": "int32", 22 | "default": 8 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/_includes/examples/custom_settings.rs: -------------------------------------------------------------------------------- 1 | use schemars::{generate::SchemaSettings, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | pub my_int: i32, 6 | pub my_bool: bool, 7 | pub my_nullable_enum: Option, 8 | } 9 | 10 | #[derive(JsonSchema)] 11 | pub enum MyEnum { 12 | StringNewType(String), 13 | StructVariant { floats: Vec }, 14 | } 15 | 16 | fn main() { 17 | let settings = SchemaSettings::draft07().with(|s| { 18 | s.meta_schema = None; 19 | s.inline_subschemas = true; 20 | }); 21 | let generator = settings.into_generator(); 22 | let schema = generator.into_root_schema_for::(); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples/custom_settings.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "MyStruct", 3 | "type": "object", 4 | "properties": { 5 | "my_bool": { 6 | "type": "boolean" 7 | }, 8 | "my_int": { 9 | "type": "integer", 10 | "format": "int32" 11 | }, 12 | "my_nullable_enum": { 13 | "anyOf": [ 14 | { 15 | "oneOf": [ 16 | { 17 | "type": "object", 18 | "properties": { 19 | "StringNewType": { 20 | "type": "string" 21 | } 22 | }, 23 | "additionalProperties": false, 24 | "required": [ 25 | "StringNewType" 26 | ] 27 | }, 28 | { 29 | "type": "object", 30 | "properties": { 31 | "StructVariant": { 32 | "type": "object", 33 | "properties": { 34 | "floats": { 35 | "type": "array", 36 | "items": { 37 | "type": "number", 38 | "format": "float" 39 | } 40 | } 41 | }, 42 | "required": [ 43 | "floats" 44 | ] 45 | } 46 | }, 47 | "additionalProperties": false, 48 | "required": [ 49 | "StructVariant" 50 | ] 51 | } 52 | ] 53 | }, 54 | { 55 | "type": "null" 56 | } 57 | ] 58 | } 59 | }, 60 | "required": [ 61 | "my_int", 62 | "my_bool" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /docs/_includes/examples/doc_comments.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | /// # My Amazing Struct 4 | /// This struct shows off generating a schema with 5 | /// a custom title and description. 6 | #[derive(JsonSchema)] 7 | pub struct MyStruct { 8 | /// # My Amazing Integer 9 | pub my_int: i32, 10 | /// This bool has a description, but no title. 11 | pub my_bool: bool, 12 | /// # A Nullable Enum 13 | /// This enum might be set, or it might not. 14 | pub my_nullable_enum: Option, 15 | } 16 | 17 | /// # My Amazing Enum 18 | #[derive(JsonSchema)] 19 | pub enum MyEnum { 20 | /// A wrapper around a `String` 21 | StringNewType(String), 22 | /// A struct-like enum variant which contains 23 | /// some floats 24 | StructVariant { 25 | /// The floats themselves 26 | floats: Vec, 27 | }, 28 | } 29 | 30 | fn main() { 31 | let schema = schema_for!(MyStruct); 32 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 33 | } 34 | -------------------------------------------------------------------------------- /docs/_includes/examples/enum_repr.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema_repr}; 2 | 3 | #[derive(JsonSchema_repr)] 4 | #[repr(u8)] 5 | enum SmallPrime { 6 | Two = 2, 7 | Three = 3, 8 | Five = 5, 9 | Seven = 7, 10 | } 11 | 12 | fn main() { 13 | let schema = schema_for!(SmallPrime); 14 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 15 | } 16 | -------------------------------------------------------------------------------- /docs/_includes/examples/enum_repr.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "SmallPrime", 4 | "type": "integer", 5 | "enum": [ 6 | 2, 7 | 3, 8 | 5, 9 | 7 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /docs/_includes/examples/from_value.rs: -------------------------------------------------------------------------------- 1 | use schemars::schema_for_value; 2 | use serde::Serialize; 3 | 4 | #[derive(Serialize)] 5 | pub struct MyStruct { 6 | pub my_int: i32, 7 | pub my_bool: bool, 8 | pub my_nullable_enum: Option, 9 | } 10 | 11 | #[derive(Serialize)] 12 | pub enum MyEnum { 13 | StringNewType(String), 14 | StructVariant { floats: Vec }, 15 | } 16 | 17 | fn main() { 18 | let schema = schema_for_value!(MyStruct { 19 | my_int: 123, 20 | my_bool: true, 21 | my_nullable_enum: Some(MyEnum::StringNewType("foo".to_string())) 22 | }); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples/from_value.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "my_bool": { 7 | "type": "boolean" 8 | }, 9 | "my_int": { 10 | "type": "integer" 11 | }, 12 | "my_nullable_enum": true 13 | }, 14 | "examples": [ 15 | { 16 | "my_bool": true, 17 | "my_int": 123, 18 | "my_nullable_enum": { 19 | "StringNewType": "foo" 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /docs/_includes/examples/main.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | pub my_int: i32, 6 | pub my_bool: bool, 7 | pub my_nullable_enum: Option, 8 | } 9 | 10 | #[derive(JsonSchema)] 11 | pub enum MyEnum { 12 | StringNewType(String), 13 | StructVariant { floats: Vec }, 14 | } 15 | 16 | fn main() { 17 | let schema = schema_for!(MyStruct); 18 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 19 | } 20 | -------------------------------------------------------------------------------- /docs/_includes/examples/main.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "my_bool": { 7 | "type": "boolean" 8 | }, 9 | "my_int": { 10 | "type": "integer", 11 | "format": "int32" 12 | }, 13 | "my_nullable_enum": { 14 | "anyOf": [ 15 | { 16 | "$ref": "#/$defs/MyEnum" 17 | }, 18 | { 19 | "type": "null" 20 | } 21 | ] 22 | } 23 | }, 24 | "required": [ 25 | "my_int", 26 | "my_bool" 27 | ], 28 | "$defs": { 29 | "MyEnum": { 30 | "oneOf": [ 31 | { 32 | "type": "object", 33 | "properties": { 34 | "StringNewType": { 35 | "type": "string" 36 | } 37 | }, 38 | "additionalProperties": false, 39 | "required": [ 40 | "StringNewType" 41 | ] 42 | }, 43 | { 44 | "type": "object", 45 | "properties": { 46 | "StructVariant": { 47 | "type": "object", 48 | "properties": { 49 | "floats": { 50 | "type": "array", 51 | "items": { 52 | "type": "number", 53 | "format": "float" 54 | } 55 | } 56 | }, 57 | "required": [ 58 | "floats" 59 | ] 60 | } 61 | }, 62 | "additionalProperties": false, 63 | "required": [ 64 | "StructVariant" 65 | ] 66 | } 67 | ] 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /docs/_includes/examples/remote_derive.rs: -------------------------------------------------------------------------------- 1 | // Pretend that this is somebody else's crate, not a module. 2 | mod other_crate { 3 | // Neither Schemars nor the other crate provides a JsonSchema impl 4 | // for this struct. 5 | pub struct Duration { 6 | pub secs: i64, 7 | pub nanos: i32, 8 | } 9 | } 10 | 11 | //////////////////////////////////////////////////////////////////////////////// 12 | 13 | use other_crate::Duration; 14 | use schemars::{schema_for, JsonSchema}; 15 | 16 | // This is just a copy of the remote data structure that Schemars can use to 17 | // create a suitable JsonSchema impl. 18 | #[derive(JsonSchema)] 19 | #[serde(remote = "Duration")] 20 | pub struct DurationDef { 21 | pub secs: i64, 22 | pub nanos: i32, 23 | } 24 | 25 | // Now the remote type can be used almost like it had its own JsonSchema impl 26 | // all along. The `with` attribute gives the path to the definition for the 27 | // remote type. Note that the real type of the field is the remote type, not 28 | // the definition type. 29 | #[derive(JsonSchema)] 30 | pub struct Process { 31 | pub command_line: String, 32 | #[serde(with = "DurationDef")] 33 | pub wall_time: Duration, 34 | // Generic types must be explicitly specified with turbofix `::<>` syntax. 35 | #[serde(with = "Vec::")] 36 | pub durations: Vec, 37 | } 38 | 39 | fn main() { 40 | let schema = schema_for!(Process); 41 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 42 | } 43 | -------------------------------------------------------------------------------- /docs/_includes/examples/remote_derive.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Process", 4 | "type": "object", 5 | "properties": { 6 | "command_line": { 7 | "type": "string" 8 | }, 9 | "durations": { 10 | "type": "array", 11 | "items": { 12 | "$ref": "#/$defs/Duration" 13 | } 14 | }, 15 | "wall_time": { 16 | "$ref": "#/$defs/Duration" 17 | } 18 | }, 19 | "required": [ 20 | "command_line", 21 | "wall_time", 22 | "durations" 23 | ], 24 | "$defs": { 25 | "Duration": { 26 | "type": "object", 27 | "properties": { 28 | "nanos": { 29 | "type": "integer", 30 | "format": "int32" 31 | }, 32 | "secs": { 33 | "type": "integer", 34 | "format": "int64" 35 | } 36 | }, 37 | "required": [ 38 | "secs", 39 | "nanos" 40 | ] 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/_includes/examples/schemars_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema, Schema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, JsonSchema)] 5 | #[schemars(rename_all = "camelCase", deny_unknown_fields, extend("x-customProperty" = "example"))] 6 | pub struct MyStruct { 7 | #[serde(rename = "thisIsOverridden")] 8 | #[schemars(rename = "myNumber", range(min = 1, max = 10), transform = remove_format)] 9 | pub my_int: i32, 10 | pub my_bool: bool, 11 | #[schemars(default)] 12 | pub my_nullable_enum: Option, 13 | #[schemars(inner(regex(pattern = "^x$")))] 14 | pub my_vec_str: Vec, 15 | } 16 | 17 | #[derive(Deserialize, Serialize, JsonSchema)] 18 | #[schemars(untagged)] 19 | pub enum MyEnum { 20 | StringNewType(#[schemars(email)] String), 21 | StructVariant { 22 | #[schemars(length(min = 1, max = 100))] 23 | floats: Vec, 24 | }, 25 | } 26 | 27 | fn remove_format(schema: &mut Schema) { 28 | schema.remove("format"); 29 | } 30 | 31 | fn main() { 32 | let schema = schema_for!(MyStruct); 33 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 34 | } 35 | -------------------------------------------------------------------------------- /docs/_includes/examples/schemars_attrs.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "myBool": { 7 | "type": "boolean" 8 | }, 9 | "myNullableEnum": { 10 | "anyOf": [ 11 | { 12 | "$ref": "#/$defs/MyEnum" 13 | }, 14 | { 15 | "type": "null" 16 | } 17 | ], 18 | "default": null 19 | }, 20 | "myNumber": { 21 | "type": "integer", 22 | "maximum": 10, 23 | "minimum": 1 24 | }, 25 | "myVecStr": { 26 | "type": "array", 27 | "items": { 28 | "type": "string", 29 | "pattern": "^x$" 30 | } 31 | } 32 | }, 33 | "additionalProperties": false, 34 | "required": [ 35 | "myNumber", 36 | "myBool", 37 | "myVecStr" 38 | ], 39 | "x-customProperty": "example", 40 | "$defs": { 41 | "MyEnum": { 42 | "anyOf": [ 43 | { 44 | "type": "string", 45 | "format": "email" 46 | }, 47 | { 48 | "type": "object", 49 | "properties": { 50 | "floats": { 51 | "type": "array", 52 | "items": { 53 | "type": "number", 54 | "format": "float" 55 | }, 56 | "maxItems": 100, 57 | "minItems": 1 58 | } 59 | }, 60 | "required": [ 61 | "floats" 62 | ] 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /docs/_includes/examples/serde_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, JsonSchema)] 5 | #[serde(rename_all = "camelCase", deny_unknown_fields)] 6 | pub struct MyStruct { 7 | #[serde(rename = "myNumber")] 8 | pub my_int: i32, 9 | pub my_bool: bool, 10 | #[serde(default)] 11 | pub my_nullable_enum: Option, 12 | } 13 | 14 | #[derive(Deserialize, Serialize, JsonSchema)] 15 | #[serde(untagged)] 16 | pub enum MyEnum { 17 | StringNewType(String), 18 | StructVariant { floats: Vec }, 19 | } 20 | 21 | fn main() { 22 | let schema = schema_for!(MyStruct); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples/serde_attrs.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "myBool": { 7 | "type": "boolean" 8 | }, 9 | "myNullableEnum": { 10 | "anyOf": [ 11 | { 12 | "$ref": "#/$defs/MyEnum" 13 | }, 14 | { 15 | "type": "null" 16 | } 17 | ], 18 | "default": null 19 | }, 20 | "myNumber": { 21 | "type": "integer", 22 | "format": "int32" 23 | } 24 | }, 25 | "additionalProperties": false, 26 | "required": [ 27 | "myNumber", 28 | "myBool" 29 | ], 30 | "$defs": { 31 | "MyEnum": { 32 | "anyOf": [ 33 | { 34 | "type": "string" 35 | }, 36 | { 37 | "type": "object", 38 | "properties": { 39 | "floats": { 40 | "type": "array", 41 | "items": { 42 | "type": "number", 43 | "format": "float" 44 | } 45 | } 46 | }, 47 | "required": [ 48 | "floats" 49 | ] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /docs/_includes/examples/serialize_contract.rs: -------------------------------------------------------------------------------- 1 | use schemars::{generate::SchemaSettings, JsonSchema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(JsonSchema, Deserialize, Serialize)] 5 | // The schema effectively ignores this `rename_all`, since it doesn't apply to serialization 6 | #[serde(rename_all(deserialize = "PascalCase"))] 7 | pub struct MyStruct { 8 | pub my_int: i32, 9 | #[serde(skip_deserializing)] 10 | pub my_read_only_bool: bool, 11 | // This property is excluded from the schema 12 | #[serde(skip_serializing)] 13 | pub my_write_only_bool: bool, 14 | // This property is excluded from the "required" properties of the schema, because it may be 15 | // be skipped during serialization 16 | #[serde(skip_serializing_if = "str::is_empty")] 17 | pub maybe_string: String, 18 | pub definitely_string: String, 19 | } 20 | 21 | fn main() { 22 | // By default, generated schemas describe how types are deserialized. 23 | // So we modify the settings here to instead generate schemas describing how it's serialized: 24 | let settings = SchemaSettings::default().for_serialize(); 25 | 26 | let generator = settings.into_generator(); 27 | let schema = generator.into_root_schema_for::(); 28 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 29 | } 30 | -------------------------------------------------------------------------------- /docs/_includes/examples/serialize_contract.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "definitely_string": { 7 | "type": "string" 8 | }, 9 | "maybe_string": { 10 | "type": "string" 11 | }, 12 | "my_int": { 13 | "type": "integer", 14 | "format": "int32" 15 | }, 16 | "my_read_only_bool": { 17 | "type": "boolean", 18 | "default": false, 19 | "readOnly": true 20 | } 21 | }, 22 | "required": [ 23 | "my_int", 24 | "my_read_only_bool", 25 | "definitely_string" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /docs/_includes/examples/validate.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | #[validate(range(min = 1, max = 10))] 6 | pub my_int: i32, 7 | pub my_bool: bool, 8 | #[validate(required)] 9 | pub my_nullable_enum: Option, 10 | } 11 | 12 | #[derive(JsonSchema)] 13 | pub enum MyEnum { 14 | StringNewType(#[validate(email)] String), 15 | StructVariant { 16 | #[validate(length(min = 1, max = 100))] 17 | floats: Vec, 18 | }, 19 | } 20 | 21 | fn main() { 22 | let schema = schema_for!(MyStruct); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples/validate.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "my_bool": { 7 | "type": "boolean" 8 | }, 9 | "my_int": { 10 | "type": "integer", 11 | "format": "int32", 12 | "maximum": 10, 13 | "minimum": 1 14 | }, 15 | "my_nullable_enum": { 16 | "oneOf": [ 17 | { 18 | "type": "object", 19 | "properties": { 20 | "StringNewType": { 21 | "type": "string", 22 | "format": "email" 23 | } 24 | }, 25 | "additionalProperties": false, 26 | "required": [ 27 | "StringNewType" 28 | ] 29 | }, 30 | { 31 | "type": "object", 32 | "properties": { 33 | "StructVariant": { 34 | "type": "object", 35 | "properties": { 36 | "floats": { 37 | "type": "array", 38 | "items": { 39 | "type": "number", 40 | "format": "float" 41 | }, 42 | "maxItems": 100, 43 | "minItems": 1 44 | } 45 | }, 46 | "required": [ 47 | "floats" 48 | ] 49 | } 50 | }, 51 | "additionalProperties": false, 52 | "required": [ 53 | "StructVariant" 54 | ] 55 | } 56 | ] 57 | } 58 | }, 59 | "required": [ 60 | "my_int", 61 | "my_bool", 62 | "my_nullable_enum" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/custom_serialization.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "bool_as_string": { 7 | "default": "false", 8 | "type": "string", 9 | "format": "boolean" 10 | }, 11 | "bool_normal": { 12 | "default": false, 13 | "type": "boolean" 14 | }, 15 | "int_as_string": { 16 | "default": "8", 17 | "type": "string" 18 | }, 19 | "int_normal": { 20 | "default": 8, 21 | "type": "integer", 22 | "format": "int32" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/custom_settings.rs: -------------------------------------------------------------------------------- 1 | use schemars::{gen::SchemaSettings, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | pub my_int: i32, 6 | pub my_bool: bool, 7 | pub my_nullable_enum: Option, 8 | } 9 | 10 | #[derive(JsonSchema)] 11 | pub enum MyEnum { 12 | StringNewType(String), 13 | StructVariant { floats: Vec }, 14 | } 15 | 16 | fn main() { 17 | let settings = SchemaSettings::draft07().with(|s| { 18 | s.option_nullable = true; 19 | s.option_add_null_type = false; 20 | }); 21 | let gen = settings.into_generator(); 22 | let schema = gen.into_root_schema_for::(); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/custom_settings.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "required": [ 6 | "my_bool", 7 | "my_int" 8 | ], 9 | "properties": { 10 | "my_bool": { 11 | "type": "boolean" 12 | }, 13 | "my_int": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "my_nullable_enum": { 18 | "allOf": [ 19 | { 20 | "$ref": "#/definitions/MyEnum" 21 | } 22 | ], 23 | "nullable": true 24 | } 25 | }, 26 | "definitions": { 27 | "MyEnum": { 28 | "oneOf": [ 29 | { 30 | "type": "object", 31 | "required": [ 32 | "StringNewType" 33 | ], 34 | "properties": { 35 | "StringNewType": { 36 | "type": "string" 37 | } 38 | }, 39 | "additionalProperties": false 40 | }, 41 | { 42 | "type": "object", 43 | "required": [ 44 | "StructVariant" 45 | ], 46 | "properties": { 47 | "StructVariant": { 48 | "type": "object", 49 | "required": [ 50 | "floats" 51 | ], 52 | "properties": { 53 | "floats": { 54 | "type": "array", 55 | "items": { 56 | "type": "number", 57 | "format": "float" 58 | } 59 | } 60 | } 61 | } 62 | }, 63 | "additionalProperties": false 64 | } 65 | ] 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/doc_comments.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | /// # My Amazing Struct 4 | /// This struct shows off generating a schema with 5 | /// a custom title and description. 6 | #[derive(JsonSchema)] 7 | pub struct MyStruct { 8 | /// # My Amazing Integer 9 | pub my_int: i32, 10 | /// This bool has a description, but no title. 11 | pub my_bool: bool, 12 | /// # A Nullable Enum 13 | /// This enum might be set, or it might not. 14 | pub my_nullable_enum: Option, 15 | } 16 | 17 | /// # My Amazing Enum 18 | #[derive(JsonSchema)] 19 | pub enum MyEnum { 20 | /// A wrapper around a `String` 21 | StringNewType(String), 22 | /// A struct-like enum variant which contains 23 | /// some floats 24 | StructVariant { 25 | /// The floats themselves 26 | floats: Vec, 27 | }, 28 | } 29 | 30 | fn main() { 31 | let schema = schema_for!(MyStruct); 32 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 33 | } 34 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/enum_repr.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema_repr}; 2 | 3 | #[derive(JsonSchema_repr)] 4 | #[repr(u8)] 5 | enum SmallPrime { 6 | Two = 2, 7 | Three = 3, 8 | Five = 5, 9 | Seven = 7, 10 | } 11 | 12 | fn main() { 13 | let schema = schema_for!(SmallPrime); 14 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 15 | } 16 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/enum_repr.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "SmallPrime", 4 | "type": "integer", 5 | "enum": [ 6 | 2, 7 | 3, 8 | 5, 9 | 7 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/from_value.rs: -------------------------------------------------------------------------------- 1 | use schemars::schema_for_value; 2 | use serde::Serialize; 3 | 4 | #[derive(Serialize)] 5 | pub struct MyStruct { 6 | pub my_int: i32, 7 | pub my_bool: bool, 8 | pub my_nullable_enum: Option, 9 | } 10 | 11 | #[derive(Serialize)] 12 | pub enum MyEnum { 13 | StringNewType(String), 14 | StructVariant { floats: Vec }, 15 | } 16 | 17 | fn main() { 18 | let schema = schema_for_value!(MyStruct { 19 | my_int: 123, 20 | my_bool: true, 21 | my_nullable_enum: Some(MyEnum::StringNewType("foo".to_string())) 22 | }); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/from_value.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "examples": [ 5 | { 6 | "my_bool": true, 7 | "my_int": 123, 8 | "my_nullable_enum": { 9 | "StringNewType": "foo" 10 | } 11 | } 12 | ], 13 | "type": "object", 14 | "properties": { 15 | "my_bool": { 16 | "type": "boolean" 17 | }, 18 | "my_int": { 19 | "type": "integer" 20 | }, 21 | "my_nullable_enum": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/main.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | pub my_int: i32, 6 | pub my_bool: bool, 7 | pub my_nullable_enum: Option, 8 | } 9 | 10 | #[derive(JsonSchema)] 11 | pub enum MyEnum { 12 | StringNewType(String), 13 | StructVariant { floats: Vec }, 14 | } 15 | 16 | fn main() { 17 | let schema = schema_for!(MyStruct); 18 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 19 | } 20 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/main.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "required": [ 6 | "my_bool", 7 | "my_int" 8 | ], 9 | "properties": { 10 | "my_bool": { 11 | "type": "boolean" 12 | }, 13 | "my_int": { 14 | "type": "integer", 15 | "format": "int32" 16 | }, 17 | "my_nullable_enum": { 18 | "anyOf": [ 19 | { 20 | "$ref": "#/definitions/MyEnum" 21 | }, 22 | { 23 | "type": "null" 24 | } 25 | ] 26 | } 27 | }, 28 | "definitions": { 29 | "MyEnum": { 30 | "oneOf": [ 31 | { 32 | "type": "object", 33 | "required": [ 34 | "StringNewType" 35 | ], 36 | "properties": { 37 | "StringNewType": { 38 | "type": "string" 39 | } 40 | }, 41 | "additionalProperties": false 42 | }, 43 | { 44 | "type": "object", 45 | "required": [ 46 | "StructVariant" 47 | ], 48 | "properties": { 49 | "StructVariant": { 50 | "type": "object", 51 | "required": [ 52 | "floats" 53 | ], 54 | "properties": { 55 | "floats": { 56 | "type": "array", 57 | "items": { 58 | "type": "number", 59 | "format": "float" 60 | } 61 | } 62 | } 63 | } 64 | }, 65 | "additionalProperties": false 66 | } 67 | ] 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/remote_derive.rs: -------------------------------------------------------------------------------- 1 | // Pretend that this is somebody else's crate, not a module. 2 | mod other_crate { 3 | // Neither Schemars nor the other crate provides a JsonSchema impl 4 | // for this struct. 5 | pub struct Duration { 6 | pub secs: i64, 7 | pub nanos: i32, 8 | } 9 | } 10 | 11 | //////////////////////////////////////////////////////////////////////////////// 12 | 13 | use other_crate::Duration; 14 | use schemars::{schema_for, JsonSchema}; 15 | 16 | // This is just a copy of the remote data structure that Schemars can use to 17 | // create a suitable JsonSchema impl. 18 | #[derive(JsonSchema)] 19 | #[serde(remote = "Duration")] 20 | pub struct DurationDef { 21 | pub secs: i64, 22 | pub nanos: i32, 23 | } 24 | 25 | // Now the remote type can be used almost like it had its own JsonSchema impl 26 | // all along. The `with` attribute gives the path to the definition for the 27 | // remote type. Note that the real type of the field is the remote type, not 28 | // the definition type. 29 | #[derive(JsonSchema)] 30 | pub struct Process { 31 | pub command_line: String, 32 | #[serde(with = "DurationDef")] 33 | pub wall_time: Duration, 34 | // Generic types must be explicitly specified with turbofix `::<>` syntax. 35 | #[serde(with = "Vec::")] 36 | pub durations: Vec, 37 | } 38 | 39 | fn main() { 40 | let schema = schema_for!(Process); 41 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 42 | } 43 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/remote_derive.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "Process", 4 | "type": "object", 5 | "required": [ 6 | "command_line", 7 | "durations", 8 | "wall_time" 9 | ], 10 | "properties": { 11 | "command_line": { 12 | "type": "string" 13 | }, 14 | "durations": { 15 | "type": "array", 16 | "items": { 17 | "$ref": "#/definitions/Duration" 18 | } 19 | }, 20 | "wall_time": { 21 | "$ref": "#/definitions/Duration" 22 | } 23 | }, 24 | "definitions": { 25 | "Duration": { 26 | "type": "object", 27 | "required": [ 28 | "nanos", 29 | "secs" 30 | ], 31 | "properties": { 32 | "nanos": { 33 | "type": "integer", 34 | "format": "int32" 35 | }, 36 | "secs": { 37 | "type": "integer", 38 | "format": "int64" 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/schemars_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, JsonSchema)] 5 | #[schemars(rename_all = "camelCase", deny_unknown_fields)] 6 | pub struct MyStruct { 7 | #[serde(rename = "thisIsOverridden")] 8 | #[schemars(rename = "myNumber", range(min = 1, max = 10))] 9 | pub my_int: i32, 10 | pub my_bool: bool, 11 | #[schemars(default)] 12 | pub my_nullable_enum: Option, 13 | #[schemars(inner(regex(pattern = "^x$")))] 14 | pub my_vec_str: Vec, 15 | } 16 | 17 | #[derive(Deserialize, Serialize, JsonSchema)] 18 | #[schemars(untagged)] 19 | pub enum MyEnum { 20 | StringNewType(#[schemars(email)] String), 21 | StructVariant { 22 | #[schemars(length(min = 1, max = 100))] 23 | floats: Vec, 24 | }, 25 | } 26 | 27 | fn main() { 28 | let schema = schema_for!(MyStruct); 29 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 30 | } 31 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/schemars_attrs.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "required": [ 6 | "myBool", 7 | "myNumber", 8 | "myVecStr" 9 | ], 10 | "properties": { 11 | "myBool": { 12 | "type": "boolean" 13 | }, 14 | "myNullableEnum": { 15 | "default": null, 16 | "anyOf": [ 17 | { 18 | "$ref": "#/definitions/MyEnum" 19 | }, 20 | { 21 | "type": "null" 22 | } 23 | ] 24 | }, 25 | "myNumber": { 26 | "type": "integer", 27 | "format": "int32", 28 | "maximum": 10.0, 29 | "minimum": 1.0 30 | }, 31 | "myVecStr": { 32 | "type": "array", 33 | "items": { 34 | "type": "string", 35 | "pattern": "^x$" 36 | } 37 | } 38 | }, 39 | "additionalProperties": false, 40 | "definitions": { 41 | "MyEnum": { 42 | "anyOf": [ 43 | { 44 | "type": "string", 45 | "format": "phone" 46 | }, 47 | { 48 | "type": "object", 49 | "required": [ 50 | "floats" 51 | ], 52 | "properties": { 53 | "floats": { 54 | "type": "array", 55 | "items": { 56 | "type": "number", 57 | "format": "float" 58 | }, 59 | "maxItems": 100, 60 | "minItems": 1 61 | } 62 | } 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/serde_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, JsonSchema)] 5 | #[serde(rename_all = "camelCase", deny_unknown_fields)] 6 | pub struct MyStruct { 7 | #[serde(rename = "myNumber")] 8 | pub my_int: i32, 9 | pub my_bool: bool, 10 | #[serde(default)] 11 | pub my_nullable_enum: Option, 12 | } 13 | 14 | #[derive(Deserialize, Serialize, JsonSchema)] 15 | #[serde(untagged)] 16 | pub enum MyEnum { 17 | StringNewType(String), 18 | StructVariant { floats: Vec }, 19 | } 20 | 21 | fn main() { 22 | let schema = schema_for!(MyStruct); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/serde_attrs.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "required": [ 6 | "myBool", 7 | "myNumber" 8 | ], 9 | "properties": { 10 | "myBool": { 11 | "type": "boolean" 12 | }, 13 | "myNullableEnum": { 14 | "default": null, 15 | "anyOf": [ 16 | { 17 | "$ref": "#/definitions/MyEnum" 18 | }, 19 | { 20 | "type": "null" 21 | } 22 | ] 23 | }, 24 | "myNumber": { 25 | "type": "integer", 26 | "format": "int32" 27 | } 28 | }, 29 | "additionalProperties": false, 30 | "definitions": { 31 | "MyEnum": { 32 | "anyOf": [ 33 | { 34 | "type": "string" 35 | }, 36 | { 37 | "type": "object", 38 | "required": [ 39 | "floats" 40 | ], 41 | "properties": { 42 | "floats": { 43 | "type": "array", 44 | "items": { 45 | "type": "number", 46 | "format": "float" 47 | } 48 | } 49 | } 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/validate.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | #[validate(range(min = 1, max = 10))] 6 | pub my_int: i32, 7 | pub my_bool: bool, 8 | #[validate(required)] 9 | pub my_nullable_enum: Option, 10 | } 11 | 12 | #[derive(JsonSchema)] 13 | pub enum MyEnum { 14 | StringNewType(#[validate(email)] String), 15 | StructVariant { 16 | #[validate(length(min = 1, max = 100))] 17 | floats: Vec, 18 | }, 19 | } 20 | 21 | fn main() { 22 | let schema = schema_for!(MyStruct); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /docs/_includes/examples_v0/validate.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "required": [ 6 | "my_bool", 7 | "my_int", 8 | "my_nullable_enum" 9 | ], 10 | "properties": { 11 | "my_bool": { 12 | "type": "boolean" 13 | }, 14 | "my_int": { 15 | "type": "integer", 16 | "format": "int32", 17 | "maximum": 10.0, 18 | "minimum": 1.0 19 | }, 20 | "my_nullable_enum": { 21 | "oneOf": [ 22 | { 23 | "type": "object", 24 | "required": [ 25 | "StringNewType" 26 | ], 27 | "properties": { 28 | "StringNewType": { 29 | "type": "string", 30 | "format": "phone" 31 | } 32 | }, 33 | "additionalProperties": false 34 | }, 35 | { 36 | "type": "object", 37 | "required": [ 38 | "StructVariant" 39 | ], 40 | "properties": { 41 | "StructVariant": { 42 | "type": "object", 43 | "required": [ 44 | "floats" 45 | ], 46 | "properties": { 47 | "floats": { 48 | "type": "array", 49 | "items": { 50 | "type": "number", 51 | "format": "float" 52 | }, 53 | "maxItems": 100, 54 | "minItems": 1 55 | } 56 | } 57 | } 58 | }, 59 | "additionalProperties": false 60 | } 61 | ] 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/_layouts/v0.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 |

This page is for the current stable release of Schemars (v0.8.x). 7 |

To view this page for the v1 version of Schemars, which is still under development, click here. 8 |

9 | 10 | {{ content }} 11 | -------------------------------------------------------------------------------- /docs/_layouts/v1.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 |

This page is for the current v1 alpha version of Schemars. This version is still under development, and further breaking changes may be introduced. 7 |

To view this page for the current stable release of Schemars (v0.8.x), click here. 8 |

9 | 10 | {{ content }} 11 | -------------------------------------------------------------------------------- /docs/_sass/color_schemes/default.scss: -------------------------------------------------------------------------------- 1 | // Overridable variables at https://github.com/pmarsceill/just-the-docs/blob/master/_sass/support/_variables.scss 2 | 3 | $body-text-color: $grey-dk-200; 4 | 5 | $nav-child-link-color: $link-color; 6 | 7 | $content-width: 60rem; 8 | 9 | $media-queries: ( 10 | xs: 320px, 11 | sm: 500px, 12 | md: $content-width, 13 | lg: $content-width + $nav-width, 14 | xl: 1400px 15 | ); -------------------------------------------------------------------------------- /docs/_sass/custom/custom.scss: -------------------------------------------------------------------------------- 1 | // Reposition/resize top-right nav buttons 2 | .aux-nav a, .aux-nav a:hover { 3 | background: none; 4 | padding: 5px; 5 | } 6 | .aux-nav a img { 7 | height: 22px; 8 | } 9 | 10 | // Enlarge and compress embedded code 11 | pre.highlight, figure.highlight { 12 | line-height: 1.2em; 13 | } 14 | code { 15 | font-size: 0.85em; 16 | } 17 | 18 | // Always expand nav menu items 19 | .nav-list:not(.nav-category-list) .nav-list-item > .nav-list { 20 | display: block; 21 | } 22 | .nav-list:not(.nav-category-list) .nav-list-expander { 23 | display: none; 24 | } 25 | 26 | // Indent text on attributes page 27 | .indented > p { 28 | margin-left: 20px; 29 | } 30 | 31 | // Hide ugly summary outline that chrome adds 32 | .main-content summary:focus { 33 | outline: none; 34 | } 35 | 36 | .main-content summary { 37 | display: list-item; 38 | font-style: italic; 39 | } -------------------------------------------------------------------------------- /docs/_v0/1-deriving.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deriving JsonSchema 3 | nav_order: 2 4 | has_children: true 5 | has_toc: false 6 | permalink: /v0/deriving/ 7 | --- 8 | 9 | # Deriving JsonSchema 10 | 11 | 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. 12 | 13 | Usually, all you need to do to use it is to add a `#[derive(JsonSchema)]` attribute to your type: 14 | 15 | ```rust 16 | use schemars::{JsonSchema, schema_for}; 17 | 18 | #[derive(JsonSchema, Debug)] 19 | struct Point { 20 | x: i32, 21 | y: i32, 22 | } 23 | 24 | fn main() { 25 | let schema = schema_for!(Point); 26 | 27 | let serialized = serde_json::to_string(&schema).unwrap(); 28 | println!("{}", serialized); 29 | } 30 | ``` 31 | 32 | 37 | -------------------------------------------------------------------------------- /docs/_v0/5-examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Examples 3 | nav_order: 6 4 | has_children: true 5 | permalink: /v0/examples/ 6 | --- 7 | 8 | # Examples 9 | -------------------------------------------------------------------------------- /docs/_v0/examples/1-derive_jsonschema.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deriving JsonSchema 3 | parent: Examples 4 | nav_order: 1 5 | summary: Deriving JsonSchema on a struct and enum. 6 | --- 7 | 8 | # Deriving JsonSchema 9 | 10 | 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. 11 | 12 | {% include example_v0.md name="main" %} 13 | -------------------------------------------------------------------------------- /docs/_v0/examples/2-serde_attrs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Serde Attributes 3 | parent: Examples 4 | nav_order: 2 5 | summary: "Deriving JsonSchema on types that use #[serde] attributes to customise serialization behaviour." 6 | --- 7 | 8 | # Using Serde Attributes 9 | 10 | 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. 11 | 12 | The list of supported `#[serde]` attributes are [documented here]({{ site.baseurl }}{% link 1.1-attributes.md %}#supported-serde-attributes). 13 | 14 | {% include example_v0.md name="serde_attrs" %} 15 | -------------------------------------------------------------------------------- /docs/_v0/examples/3-schemars_attrs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Schemars Attributes 3 | parent: Examples 4 | nav_order: 3 5 | summary: "Deriving JsonSchema on types that use #[schemars] attributes to customise serialization behaviour." 6 | --- 7 | 8 | # Using Serde Attributes 9 | 10 | `#[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. 11 | 12 | {% include example_v0.md name="schemars_attrs" %} 13 | -------------------------------------------------------------------------------- /docs/_v0/examples/4-custom_settings.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Schema Settings 3 | parent: Examples 4 | nav_order: 4 5 | summary: Generating a schema using custom settings which changes how Option is handled. 6 | --- 7 | 8 | # Custom Schema Settings 9 | 10 | The `gen` module allows you to customise how schemas are generated. For example, the default behaviour for `Option` is to include `null` in the schema's `type`s, but we can instead add a `nullable` property to its schema: 11 | 12 | {% include example_v0.md name="custom_settings" %} 13 | -------------------------------------------------------------------------------- /docs/_v0/examples/5-remote_derive.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Derive for Remote Crate 3 | parent: Examples 4 | nav_order: 5 5 | summary: Deriving JsonSchema implementations for a type in somebody else's crate. 6 | --- 7 | 8 | # Deriving JsonSchema for a Type in a Different Crate 9 | 10 | 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. 11 | 12 | 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. 13 | 14 | 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)! 15 | 16 | {% include example_v0.md name="remote_derive" %} 17 | -------------------------------------------------------------------------------- /docs/_v0/examples/6-doc_comments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Doc Comments 3 | parent: Examples 4 | nav_order: 6 5 | summary: Giving schemas a custom title and/or description using doc comments. 6 | --- 7 | 8 | # Setting a Custom Title and/or Description Using Doc Comments 9 | 10 | 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`. 11 | 12 | {% include example_v0.md name="doc_comments" %} 13 | -------------------------------------------------------------------------------- /docs/_v0/examples/7-custom_serialization.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Serialization 3 | parent: Examples 4 | nav_order: 7 5 | summary: >- 6 | If a field has a #[serde(with = "path")] attribute where "path" is not a type that implements JsonSchema, 7 | then in order to derive JsonSchema on the type, it must also have a #[schemars(with = "Type")] attribute, 8 | where "Type" implements JsonSchema. 9 | --- 10 | 11 | # Deriving JsonSchema with Fields Using Custom Serialization 12 | 13 | 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`. 14 | 15 | 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. 16 | 17 | {% include example_v0.md name="custom_serialization" %} 18 | 19 | Note that the `default` values in the schema are serialized as strings where appropriate. 20 | -------------------------------------------------------------------------------- /docs/_v0/examples/8-enum_repr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Serialize Enum as Number (serde_repr) 3 | parent: Examples 4 | nav_order: 8 5 | summary: >- 6 | Generating a schema for with a C-like enum compatible with serde_repr. 7 | --- 8 | 9 | # Serialize Enum as Number (serde_repr Compatibility) 10 | 11 | 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. 12 | 13 | {% include example_v0.md name="enum_repr" %} 14 | -------------------------------------------------------------------------------- /docs/_v0/examples/9-from_value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Generate Schema from Example Value 3 | parent: Examples 4 | nav_order: 9 5 | summary: >- 6 | Generating a schema for a serializable value. 7 | --- 8 | 9 | # Generate Schema from Example Value 10 | 11 | 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. 12 | 13 | {% include example_v0.md name="from_value" %} 14 | 15 | Note that the schema for the enum is not very useful in this case, since schemars doesn't know anything about the second variant. 16 | -------------------------------------------------------------------------------- /docs/_v0/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | has_children: true 4 | nav_order: 1 5 | permalink: /v0/ 6 | --- 7 | 8 | # Schemars 9 | 10 | Schemars is a library to generate JSON Schema documents from Rust data structures. 11 | 12 | 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. 13 | 14 | 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. 15 | 16 | ## Basic Usage 17 | 18 | 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. 19 | 20 | {% include example.md name="main" %} 21 | -------------------------------------------------------------------------------- /docs/docker-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | services: 3 | jekyll: 4 | build: 5 | context: . 6 | volumes: 7 | - ".:/docs" 8 | working_dir: "/docs" 9 | ports: 10 | - 4000:4000 -------------------------------------------------------------------------------- /docs/examples/1-derive_jsonschema.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deriving JsonSchema 3 | parent: Examples 4 | nav_order: 1 5 | summary: Deriving JsonSchema on a struct and enum. 6 | --- 7 | 8 | # Deriving JsonSchema 9 | 10 | 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. 11 | 12 | {% include example.md name="main" %} 13 | -------------------------------------------------------------------------------- /docs/examples/2-serde_attrs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Serde Attributes 3 | parent: Examples 4 | nav_order: 2 5 | summary: "Deriving JsonSchema on types that use #[serde] attributes to customise serialization behaviour." 6 | --- 7 | 8 | # Using Serde Attributes 9 | 10 | 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. 11 | 12 | The list of supported `#[serde]` attributes are [documented here]({{ site.baseurl }}{% link 1.1-attributes.md %}#supported-serde-attributes). 13 | 14 | {% include example.md name="serde_attrs" %} 15 | -------------------------------------------------------------------------------- /docs/examples/3-schemars_attrs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Schemars Attributes 3 | parent: Examples 4 | nav_order: 3 5 | summary: "Deriving JsonSchema on types that use #[schemars] attributes to customise serialization behaviour." 6 | --- 7 | 8 | # Using Serde Attributes 9 | 10 | `#[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. 11 | 12 | {% include example.md name="schemars_attrs" %} 13 | -------------------------------------------------------------------------------- /docs/examples/4-custom_settings.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Schema Settings 3 | parent: Examples 4 | nav_order: 4 5 | summary: Generating a schema using custom settings which changes how Option is handled. 6 | --- 7 | 8 | # Custom Schema Settings 9 | 10 | The `generate` module allows you to customise how schemas are generated. For example, the default behaviour for `Option` is to include `null` in the schema's `type`s, but we can instead add a `nullable` property to its schema: 11 | 12 | {% include example.md name="custom_settings" %} 13 | -------------------------------------------------------------------------------- /docs/examples/5-remote_derive.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Derive for Remote Crate 3 | parent: Examples 4 | nav_order: 5 5 | summary: Deriving JsonSchema implementations for a type in somebody else's crate. 6 | --- 7 | 8 | # Deriving JsonSchema for a Type in a Different Crate 9 | 10 | 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. 11 | 12 | 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. 13 | 14 | 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)! 15 | 16 | {% include example.md name="remote_derive" %} 17 | -------------------------------------------------------------------------------- /docs/examples/6-doc_comments.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Doc Comments 3 | parent: Examples 4 | nav_order: 6 5 | summary: Giving schemas a custom title and/or description using doc comments. 6 | --- 7 | 8 | # Setting a Custom Title and/or Description Using Doc Comments 9 | 10 | 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`. 11 | 12 | {% include example.md name="doc_comments" %} 13 | -------------------------------------------------------------------------------- /docs/examples/7-custom_serialization.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Serialization 3 | parent: Examples 4 | nav_order: 7 5 | summary: >- 6 | If a field has a #[serde(with = "path")] attribute where "path" is not a type that implements JsonSchema, 7 | then in order to derive JsonSchema on the type, it must also have a #[schemars(with = "Type")] attribute, 8 | where "Type" implements JsonSchema. 9 | --- 10 | 11 | # Deriving JsonSchema with Fields Using Custom Serialization 12 | 13 | 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`. 14 | 15 | 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. 16 | 17 | {% include example.md name="custom_serialization" %} 18 | 19 | Note that the `default` values in the schema are serialized as strings where appropriate. 20 | -------------------------------------------------------------------------------- /docs/examples/8-enum_repr.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Serialize Enum as Number (serde_repr) 3 | parent: Examples 4 | nav_order: 8 5 | summary: >- 6 | Generating a schema for with a C-like enum compatible with serde_repr. 7 | --- 8 | 9 | # Serialize Enum as Number (serde_repr Compatibility) 10 | 11 | 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. 12 | 13 | {% include example.md name="enum_repr" %} 14 | -------------------------------------------------------------------------------- /docs/examples/9-from_value.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Generate Schema from Example Value 3 | parent: Examples 4 | nav_order: 9 5 | summary: >- 6 | Generating a schema for a serializable value. 7 | --- 8 | 9 | # Generate Schema from Example Value 10 | 11 | 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. 12 | 13 | {% include example.md name="from_value" %} 14 | 15 | Note that the schema for the enum is not very useful in this case, since schemars doesn't know anything about the second variant. 16 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | nav_order: 1 4 | --- 5 | 6 | # Schemars 7 | 8 | Schemars is a library to generate JSON Schema documents from Rust data structures. 9 | 10 | This is built on Rust's trait system - any type which implements the [`JsonSchema`](https://docs.rs/schemars/1.0.0--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. 11 | 12 | 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. 13 | 14 | ## Basic Usage 15 | 16 | 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. 17 | 18 | {% include example.md name="main" %} 19 | -------------------------------------------------------------------------------- /schemars/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | /tests/actual/*.json 5 | /tests/expected/README.md -------------------------------------------------------------------------------- /schemars/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /schemars/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /schemars/docs-rs-custom.css: -------------------------------------------------------------------------------- 1 | ../docs-rs-custom.css -------------------------------------------------------------------------------- /schemars/examples/custom_serialization.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema, Schema, SchemaGenerator}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | // `int_as_string` and `bool_as_string` use the schema for `String`. 5 | #[derive(Default, Deserialize, Serialize, JsonSchema)] 6 | pub struct MyStruct { 7 | #[serde(default = "eight", with = "as_string")] 8 | #[schemars(with = "String")] 9 | pub int_as_string: i32, 10 | 11 | #[serde(default = "eight")] 12 | pub int_normal: i32, 13 | 14 | #[serde(default, with = "as_string")] 15 | #[schemars(schema_with = "make_custom_schema")] 16 | pub bool_as_string: bool, 17 | 18 | #[serde(default)] 19 | pub bool_normal: bool, 20 | } 21 | 22 | fn make_custom_schema(generator: &mut SchemaGenerator) -> Schema { 23 | let mut schema = String::json_schema(generator); 24 | schema.insert("format".into(), "boolean".into()); 25 | schema 26 | } 27 | 28 | fn eight() -> i32 { 29 | 8 30 | } 31 | 32 | // This module serializes values as strings 33 | mod as_string { 34 | use serde::{de::Error, Deserialize, Deserializer, Serializer}; 35 | 36 | pub fn serialize(value: &T, serializer: S) -> Result 37 | where 38 | T: std::fmt::Display, 39 | S: Serializer, 40 | { 41 | serializer.collect_str(value) 42 | } 43 | 44 | pub fn deserialize<'de, T, D>(deserializer: D) -> Result 45 | where 46 | T: std::str::FromStr, 47 | D: Deserializer<'de>, 48 | { 49 | let string = String::deserialize(deserializer)?; 50 | string 51 | .parse() 52 | .map_err(|_| D::Error::custom("Input was not valid")) 53 | } 54 | } 55 | 56 | fn main() { 57 | let schema = schema_for!(MyStruct); 58 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 59 | } 60 | -------------------------------------------------------------------------------- /schemars/examples/custom_serialization.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "bool_as_string": { 7 | "type": "string", 8 | "format": "boolean", 9 | "default": "false" 10 | }, 11 | "bool_normal": { 12 | "type": "boolean", 13 | "default": false 14 | }, 15 | "int_as_string": { 16 | "type": "string", 17 | "default": "8" 18 | }, 19 | "int_normal": { 20 | "type": "integer", 21 | "format": "int32", 22 | "default": 8 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /schemars/examples/custom_settings.rs: -------------------------------------------------------------------------------- 1 | use schemars::{generate::SchemaSettings, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | pub my_int: i32, 6 | pub my_bool: bool, 7 | pub my_nullable_enum: Option, 8 | } 9 | 10 | #[derive(JsonSchema)] 11 | pub enum MyEnum { 12 | StringNewType(String), 13 | StructVariant { floats: Vec }, 14 | } 15 | 16 | fn main() { 17 | let settings = SchemaSettings::draft07().with(|s| { 18 | s.meta_schema = None; 19 | s.inline_subschemas = true; 20 | }); 21 | let generator = settings.into_generator(); 22 | let schema = generator.into_root_schema_for::(); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /schemars/examples/custom_settings.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "MyStruct", 3 | "type": "object", 4 | "properties": { 5 | "my_bool": { 6 | "type": "boolean" 7 | }, 8 | "my_int": { 9 | "type": "integer", 10 | "format": "int32" 11 | }, 12 | "my_nullable_enum": { 13 | "anyOf": [ 14 | { 15 | "oneOf": [ 16 | { 17 | "type": "object", 18 | "properties": { 19 | "StringNewType": { 20 | "type": "string" 21 | } 22 | }, 23 | "additionalProperties": false, 24 | "required": [ 25 | "StringNewType" 26 | ] 27 | }, 28 | { 29 | "type": "object", 30 | "properties": { 31 | "StructVariant": { 32 | "type": "object", 33 | "properties": { 34 | "floats": { 35 | "type": "array", 36 | "items": { 37 | "type": "number", 38 | "format": "float" 39 | } 40 | } 41 | }, 42 | "required": [ 43 | "floats" 44 | ] 45 | } 46 | }, 47 | "additionalProperties": false, 48 | "required": [ 49 | "StructVariant" 50 | ] 51 | } 52 | ] 53 | }, 54 | { 55 | "type": "null" 56 | } 57 | ] 58 | } 59 | }, 60 | "required": [ 61 | "my_int", 62 | "my_bool" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /schemars/examples/doc_comments.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | /// # My Amazing Struct 4 | /// This struct shows off generating a schema with 5 | /// a custom title and description. 6 | #[derive(JsonSchema)] 7 | pub struct MyStruct { 8 | /// # My Amazing Integer 9 | pub my_int: i32, 10 | /// This bool has a description, but no title. 11 | pub my_bool: bool, 12 | /// # A Nullable Enum 13 | /// This enum might be set, or it might not. 14 | pub my_nullable_enum: Option, 15 | } 16 | 17 | /// # My Amazing Enum 18 | #[derive(JsonSchema)] 19 | pub enum MyEnum { 20 | /// A wrapper around a `String` 21 | StringNewType(String), 22 | /// A struct-like enum variant which contains 23 | /// some floats 24 | StructVariant { 25 | /// The floats themselves 26 | floats: Vec, 27 | }, 28 | } 29 | 30 | fn main() { 31 | let schema = schema_for!(MyStruct); 32 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 33 | } 34 | -------------------------------------------------------------------------------- /schemars/examples/enum_repr.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema_repr}; 2 | 3 | #[derive(JsonSchema_repr)] 4 | #[repr(u8)] 5 | enum SmallPrime { 6 | Two = 2, 7 | Three = 3, 8 | Five = 5, 9 | Seven = 7, 10 | } 11 | 12 | fn main() { 13 | let schema = schema_for!(SmallPrime); 14 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 15 | } 16 | -------------------------------------------------------------------------------- /schemars/examples/enum_repr.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "SmallPrime", 4 | "type": "integer", 5 | "enum": [ 6 | 2, 7 | 3, 8 | 5, 9 | 7 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /schemars/examples/from_value.rs: -------------------------------------------------------------------------------- 1 | use schemars::schema_for_value; 2 | use serde::Serialize; 3 | 4 | #[derive(Serialize)] 5 | pub struct MyStruct { 6 | pub my_int: i32, 7 | pub my_bool: bool, 8 | pub my_nullable_enum: Option, 9 | } 10 | 11 | #[derive(Serialize)] 12 | pub enum MyEnum { 13 | StringNewType(String), 14 | StructVariant { floats: Vec }, 15 | } 16 | 17 | fn main() { 18 | let schema = schema_for_value!(MyStruct { 19 | my_int: 123, 20 | my_bool: true, 21 | my_nullable_enum: Some(MyEnum::StringNewType("foo".to_string())) 22 | }); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /schemars/examples/from_value.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "my_bool": { 7 | "type": "boolean" 8 | }, 9 | "my_int": { 10 | "type": "integer" 11 | }, 12 | "my_nullable_enum": true 13 | }, 14 | "examples": [ 15 | { 16 | "my_bool": true, 17 | "my_int": 123, 18 | "my_nullable_enum": { 19 | "StringNewType": "foo" 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /schemars/examples/main.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | pub my_int: i32, 6 | pub my_bool: bool, 7 | pub my_nullable_enum: Option, 8 | } 9 | 10 | #[derive(JsonSchema)] 11 | pub enum MyEnum { 12 | StringNewType(String), 13 | StructVariant { floats: Vec }, 14 | } 15 | 16 | fn main() { 17 | let schema = schema_for!(MyStruct); 18 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 19 | } 20 | -------------------------------------------------------------------------------- /schemars/examples/main.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "my_bool": { 7 | "type": "boolean" 8 | }, 9 | "my_int": { 10 | "type": "integer", 11 | "format": "int32" 12 | }, 13 | "my_nullable_enum": { 14 | "anyOf": [ 15 | { 16 | "$ref": "#/$defs/MyEnum" 17 | }, 18 | { 19 | "type": "null" 20 | } 21 | ] 22 | } 23 | }, 24 | "required": [ 25 | "my_int", 26 | "my_bool" 27 | ], 28 | "$defs": { 29 | "MyEnum": { 30 | "oneOf": [ 31 | { 32 | "type": "object", 33 | "properties": { 34 | "StringNewType": { 35 | "type": "string" 36 | } 37 | }, 38 | "additionalProperties": false, 39 | "required": [ 40 | "StringNewType" 41 | ] 42 | }, 43 | { 44 | "type": "object", 45 | "properties": { 46 | "StructVariant": { 47 | "type": "object", 48 | "properties": { 49 | "floats": { 50 | "type": "array", 51 | "items": { 52 | "type": "number", 53 | "format": "float" 54 | } 55 | } 56 | }, 57 | "required": [ 58 | "floats" 59 | ] 60 | } 61 | }, 62 | "additionalProperties": false, 63 | "required": [ 64 | "StructVariant" 65 | ] 66 | } 67 | ] 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /schemars/examples/remote_derive.rs: -------------------------------------------------------------------------------- 1 | // Pretend that this is somebody else's crate, not a module. 2 | mod other_crate { 3 | // Neither Schemars nor the other crate provides a JsonSchema impl 4 | // for this struct. 5 | pub struct Duration { 6 | pub secs: i64, 7 | pub nanos: i32, 8 | } 9 | } 10 | 11 | //////////////////////////////////////////////////////////////////////////////// 12 | 13 | use other_crate::Duration; 14 | use schemars::{schema_for, JsonSchema}; 15 | 16 | // This is just a copy of the remote data structure that Schemars can use to 17 | // create a suitable JsonSchema impl. 18 | #[derive(JsonSchema)] 19 | #[serde(remote = "Duration")] 20 | pub struct DurationDef { 21 | pub secs: i64, 22 | pub nanos: i32, 23 | } 24 | 25 | // Now the remote type can be used almost like it had its own JsonSchema impl 26 | // all along. The `with` attribute gives the path to the definition for the 27 | // remote type. Note that the real type of the field is the remote type, not 28 | // the definition type. 29 | #[derive(JsonSchema)] 30 | pub struct Process { 31 | pub command_line: String, 32 | #[serde(with = "DurationDef")] 33 | pub wall_time: Duration, 34 | // Generic types must be explicitly specified with turbofix `::<>` syntax. 35 | #[serde(with = "Vec::")] 36 | pub durations: Vec, 37 | } 38 | 39 | fn main() { 40 | let schema = schema_for!(Process); 41 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 42 | } 43 | -------------------------------------------------------------------------------- /schemars/examples/remote_derive.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Process", 4 | "type": "object", 5 | "properties": { 6 | "command_line": { 7 | "type": "string" 8 | }, 9 | "durations": { 10 | "type": "array", 11 | "items": { 12 | "$ref": "#/$defs/Duration" 13 | } 14 | }, 15 | "wall_time": { 16 | "$ref": "#/$defs/Duration" 17 | } 18 | }, 19 | "required": [ 20 | "command_line", 21 | "wall_time", 22 | "durations" 23 | ], 24 | "$defs": { 25 | "Duration": { 26 | "type": "object", 27 | "properties": { 28 | "nanos": { 29 | "type": "integer", 30 | "format": "int32" 31 | }, 32 | "secs": { 33 | "type": "integer", 34 | "format": "int64" 35 | } 36 | }, 37 | "required": [ 38 | "secs", 39 | "nanos" 40 | ] 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /schemars/examples/schemars_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema, Schema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, JsonSchema)] 5 | #[schemars(rename_all = "camelCase", deny_unknown_fields, extend("x-customProperty" = "example"))] 6 | pub struct MyStruct { 7 | #[serde(rename = "thisIsOverridden")] 8 | #[schemars(rename = "myNumber", range(min = 1, max = 10), transform = remove_format)] 9 | pub my_int: i32, 10 | pub my_bool: bool, 11 | #[schemars(default)] 12 | pub my_nullable_enum: Option, 13 | #[schemars(inner(regex(pattern = "^x$")))] 14 | pub my_vec_str: Vec, 15 | } 16 | 17 | #[derive(Deserialize, Serialize, JsonSchema)] 18 | #[schemars(untagged)] 19 | pub enum MyEnum { 20 | StringNewType(#[schemars(email)] String), 21 | StructVariant { 22 | #[schemars(length(min = 1, max = 100))] 23 | floats: Vec, 24 | }, 25 | } 26 | 27 | fn remove_format(schema: &mut Schema) { 28 | schema.remove("format"); 29 | } 30 | 31 | fn main() { 32 | let schema = schema_for!(MyStruct); 33 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 34 | } 35 | -------------------------------------------------------------------------------- /schemars/examples/schemars_attrs.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "myBool": { 7 | "type": "boolean" 8 | }, 9 | "myNullableEnum": { 10 | "anyOf": [ 11 | { 12 | "$ref": "#/$defs/MyEnum" 13 | }, 14 | { 15 | "type": "null" 16 | } 17 | ], 18 | "default": null 19 | }, 20 | "myNumber": { 21 | "type": "integer", 22 | "maximum": 10, 23 | "minimum": 1 24 | }, 25 | "myVecStr": { 26 | "type": "array", 27 | "items": { 28 | "type": "string", 29 | "pattern": "^x$" 30 | } 31 | } 32 | }, 33 | "additionalProperties": false, 34 | "required": [ 35 | "myNumber", 36 | "myBool", 37 | "myVecStr" 38 | ], 39 | "x-customProperty": "example", 40 | "$defs": { 41 | "MyEnum": { 42 | "anyOf": [ 43 | { 44 | "type": "string", 45 | "format": "email" 46 | }, 47 | { 48 | "type": "object", 49 | "properties": { 50 | "floats": { 51 | "type": "array", 52 | "items": { 53 | "type": "number", 54 | "format": "float" 55 | }, 56 | "maxItems": 100, 57 | "minItems": 1 58 | } 59 | }, 60 | "required": [ 61 | "floats" 62 | ] 63 | } 64 | ] 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /schemars/examples/serde_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(Deserialize, Serialize, JsonSchema)] 5 | #[serde(rename_all = "camelCase", deny_unknown_fields)] 6 | pub struct MyStruct { 7 | #[serde(rename = "myNumber")] 8 | pub my_int: i32, 9 | pub my_bool: bool, 10 | #[serde(default)] 11 | pub my_nullable_enum: Option, 12 | } 13 | 14 | #[derive(Deserialize, Serialize, JsonSchema)] 15 | #[serde(untagged)] 16 | pub enum MyEnum { 17 | StringNewType(String), 18 | StructVariant { floats: Vec }, 19 | } 20 | 21 | fn main() { 22 | let schema = schema_for!(MyStruct); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /schemars/examples/serde_attrs.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "myBool": { 7 | "type": "boolean" 8 | }, 9 | "myNullableEnum": { 10 | "anyOf": [ 11 | { 12 | "$ref": "#/$defs/MyEnum" 13 | }, 14 | { 15 | "type": "null" 16 | } 17 | ], 18 | "default": null 19 | }, 20 | "myNumber": { 21 | "type": "integer", 22 | "format": "int32" 23 | } 24 | }, 25 | "additionalProperties": false, 26 | "required": [ 27 | "myNumber", 28 | "myBool" 29 | ], 30 | "$defs": { 31 | "MyEnum": { 32 | "anyOf": [ 33 | { 34 | "type": "string" 35 | }, 36 | { 37 | "type": "object", 38 | "properties": { 39 | "floats": { 40 | "type": "array", 41 | "items": { 42 | "type": "number", 43 | "format": "float" 44 | } 45 | } 46 | }, 47 | "required": [ 48 | "floats" 49 | ] 50 | } 51 | ] 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /schemars/examples/serialize_contract.rs: -------------------------------------------------------------------------------- 1 | use schemars::{generate::SchemaSettings, JsonSchema}; 2 | use serde::{Deserialize, Serialize}; 3 | 4 | #[derive(JsonSchema, Deserialize, Serialize)] 5 | // The schema effectively ignores this `rename_all`, since it doesn't apply to serialization 6 | #[serde(rename_all(deserialize = "PascalCase"))] 7 | pub struct MyStruct { 8 | pub my_int: i32, 9 | #[serde(skip_deserializing)] 10 | pub my_read_only_bool: bool, 11 | // This property is excluded from the schema 12 | #[serde(skip_serializing)] 13 | pub my_write_only_bool: bool, 14 | // This property is excluded from the "required" properties of the schema, because it may be 15 | // be skipped during serialization 16 | #[serde(skip_serializing_if = "str::is_empty")] 17 | pub maybe_string: String, 18 | pub definitely_string: String, 19 | } 20 | 21 | fn main() { 22 | // By default, generated schemas describe how types are deserialized. 23 | // So we modify the settings here to instead generate schemas describing how it's serialized: 24 | let settings = SchemaSettings::default().for_serialize(); 25 | 26 | let generator = settings.into_generator(); 27 | let schema = generator.into_root_schema_for::(); 28 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 29 | } 30 | -------------------------------------------------------------------------------- /schemars/examples/serialize_contract.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "definitely_string": { 7 | "type": "string" 8 | }, 9 | "maybe_string": { 10 | "type": "string" 11 | }, 12 | "my_int": { 13 | "type": "integer", 14 | "format": "int32" 15 | }, 16 | "my_read_only_bool": { 17 | "type": "boolean", 18 | "default": false, 19 | "readOnly": true 20 | } 21 | }, 22 | "required": [ 23 | "my_int", 24 | "my_read_only_bool", 25 | "definitely_string" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /schemars/examples/validate.rs: -------------------------------------------------------------------------------- 1 | use schemars::{schema_for, JsonSchema}; 2 | 3 | #[derive(JsonSchema)] 4 | pub struct MyStruct { 5 | #[validate(range(min = 1, max = 10))] 6 | pub my_int: i32, 7 | pub my_bool: bool, 8 | #[validate(required)] 9 | pub my_nullable_enum: Option, 10 | } 11 | 12 | #[derive(JsonSchema)] 13 | pub enum MyEnum { 14 | StringNewType(#[validate(email)] String), 15 | StructVariant { 16 | #[validate(length(min = 1, max = 100))] 17 | floats: Vec, 18 | }, 19 | } 20 | 21 | fn main() { 22 | let schema = schema_for!(MyStruct); 23 | println!("{}", serde_json::to_string_pretty(&schema).unwrap()); 24 | } 25 | -------------------------------------------------------------------------------- /schemars/examples/validate.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "my_bool": { 7 | "type": "boolean" 8 | }, 9 | "my_int": { 10 | "type": "integer", 11 | "format": "int32", 12 | "maximum": 10, 13 | "minimum": 1 14 | }, 15 | "my_nullable_enum": { 16 | "oneOf": [ 17 | { 18 | "type": "object", 19 | "properties": { 20 | "StringNewType": { 21 | "type": "string", 22 | "format": "email" 23 | } 24 | }, 25 | "additionalProperties": false, 26 | "required": [ 27 | "StringNewType" 28 | ] 29 | }, 30 | { 31 | "type": "object", 32 | "properties": { 33 | "StructVariant": { 34 | "type": "object", 35 | "properties": { 36 | "floats": { 37 | "type": "array", 38 | "items": { 39 | "type": "number", 40 | "format": "float" 41 | }, 42 | "maxItems": 100, 43 | "minItems": 1 44 | } 45 | }, 46 | "required": [ 47 | "floats" 48 | ] 49 | } 50 | }, 51 | "additionalProperties": false, 52 | "required": [ 53 | "StructVariant" 54 | ] 55 | } 56 | ] 57 | } 58 | }, 59 | "required": [ 60 | "my_int", 61 | "my_bool", 62 | "my_nullable_enum" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /schemars/src/consts.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Constants associated with JSON Schema generation. 3 | */ 4 | 5 | /// Known values of the `$schema` property. 6 | pub mod meta_schemas { 7 | /// The mata-schema for [JSON Schema Draft 7](https://json-schema.org/specification-links#draft-7) 8 | /// (`http://json-schema.org/draft-07/schema#`). 9 | pub const DRAFT07: &str = "http://json-schema.org/draft-07/schema#"; 10 | 11 | /// The mata-schema for [JSON Schema 2019-09](https://json-schema.org/specification-links#draft-2019-09-(formerly-known-as-draft-8)) 12 | /// (`https://json-schema.org/draft/2019-09/schema`). 13 | pub const DRAFT2019_09: &str = "https://json-schema.org/draft/2019-09/schema"; 14 | 15 | /// The mata-schema for [JSON Schema 2020-12](https://json-schema.org/specification-links#2020-12) 16 | /// (`https://json-schema.org/draft/2020-12/schema`). 17 | pub const DRAFT2020_12: &str = "https://json-schema.org/draft/2020-12/schema"; 18 | 19 | /// The mata-schema for [OpenAPI 3.0 schemas](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.4.md#schema) 20 | /// (`https://spec.openapis.org/oas/3.0/schema/2024-10-18#/definitions/Schema`). 21 | /// 22 | /// This should rarely be encountered in practice, as OpenAPI schemas are typically only 23 | /// embedded within OpenAPI documents, so do not have a `$schema` property set. 24 | pub const OPENAPI3: &str = 25 | "https://spec.openapis.org/oas/3.0/schema/2024-10-18#/definitions/Schema"; 26 | } 27 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/array.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::_alloc_prelude::*; 3 | use crate::{json_schema, JsonSchema, Schema}; 4 | use alloc::borrow::Cow; 5 | 6 | // Does not require T: JsonSchema. 7 | impl JsonSchema for [T; 0] { 8 | inline_schema!(); 9 | 10 | fn schema_name() -> Cow<'static, str> { 11 | "EmptyArray".into() 12 | } 13 | 14 | fn schema_id() -> Cow<'static, str> { 15 | "[]".into() 16 | } 17 | 18 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 19 | json_schema!({ 20 | "type": "array", 21 | "maxItems": 0, 22 | }) 23 | } 24 | } 25 | 26 | macro_rules! array_impls { 27 | ($($len:tt)+) => { 28 | $( 29 | impl JsonSchema for [T; $len] { 30 | inline_schema!(); 31 | 32 | fn schema_name() -> Cow<'static, str> { 33 | format!("Array_size_{}_of_{}", $len, T::schema_name()).into() 34 | } 35 | 36 | fn schema_id() -> Cow<'static, str> { 37 | format!("[{}; {}]", $len, T::schema_id()).into() 38 | } 39 | 40 | fn json_schema(generator: &mut SchemaGenerator) -> Schema { 41 | json_schema!({ 42 | "type": "array", 43 | "items": serde_json::Value::from(generator.subschema_for::()), 44 | "minItems": $len, 45 | "maxItems": $len, 46 | }) 47 | } 48 | } 49 | )+ 50 | } 51 | } 52 | 53 | array_impls! { 54 | 1 2 3 4 5 6 7 8 9 10 55 | 11 12 13 14 15 16 17 18 19 20 56 | 21 22 23 24 25 26 27 28 29 30 57 | 31 32 58 | } 59 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/arrayvec07.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::_alloc_prelude::*; 3 | use crate::{json_schema, JsonSchema, Schema}; 4 | use arrayvec07::{ArrayString, ArrayVec}; 5 | 6 | // Do not set maxLength on the schema as that describes length in characters, but we only 7 | // know max length in bytes. 8 | forward_impl!(( JsonSchema for ArrayString) => String); 9 | 10 | impl JsonSchema for ArrayVec 11 | where 12 | T: JsonSchema, 13 | { 14 | inline_schema!(); 15 | 16 | fn schema_name() -> alloc::borrow::Cow<'static, str> { 17 | format!("Array_up_to_size_{}_of_{}", CAP, T::schema_name()).into() 18 | } 19 | 20 | fn json_schema(generator: &mut SchemaGenerator) -> Schema { 21 | json_schema!({ 22 | "type": "array", 23 | "items": generator.subschema_for::(), 24 | "maxItems": CAP 25 | }) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/atomic.rs: -------------------------------------------------------------------------------- 1 | use core::sync::atomic::*; 2 | 3 | #[cfg(target_has_atomic = "8")] 4 | forward_impl!(AtomicBool => bool); 5 | 6 | #[cfg(target_has_atomic = "8")] 7 | forward_impl!(AtomicI8 => i8); 8 | 9 | #[cfg(target_has_atomic = "16")] 10 | forward_impl!(AtomicI16 => i16); 11 | 12 | #[cfg(target_has_atomic = "32")] 13 | forward_impl!(AtomicI32 => i32); 14 | 15 | #[cfg(target_has_atomic = "64")] 16 | forward_impl!(AtomicI64 => i64); 17 | 18 | #[cfg(target_has_atomic = "ptr")] 19 | forward_impl!(AtomicIsize => isize); 20 | 21 | #[cfg(target_has_atomic = "8")] 22 | forward_impl!(AtomicU8 => u8); 23 | 24 | #[cfg(target_has_atomic = "16")] 25 | forward_impl!(AtomicU16 => u16); 26 | 27 | #[cfg(target_has_atomic = "32")] 28 | forward_impl!(AtomicU32 => u32); 29 | 30 | #[cfg(target_has_atomic = "64")] 31 | forward_impl!(AtomicU64 => u64); 32 | 33 | #[cfg(target_has_atomic = "ptr")] 34 | forward_impl!(AtomicUsize => usize); 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::*; 39 | use crate::schema_for; 40 | use pretty_assertions::assert_eq; 41 | 42 | #[test] 43 | fn schema_for_atomics() { 44 | let atomic_schema = schema_for!(( 45 | AtomicBool, 46 | AtomicI8, 47 | AtomicI16, 48 | AtomicI32, 49 | AtomicI64, 50 | AtomicIsize, 51 | AtomicU8, 52 | AtomicU16, 53 | AtomicU32, 54 | AtomicU64, 55 | AtomicUsize, 56 | )); 57 | let basic_schema = schema_for!((bool, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize)); 58 | assert_eq!(atomic_schema, basic_schema); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/bytes1.rs: -------------------------------------------------------------------------------- 1 | use crate::_alloc_prelude::*; 2 | use crate::generate::Contract; 3 | use crate::{JsonSchema, Schema}; 4 | use alloc::borrow::Cow; 5 | use serde_json::Value; 6 | 7 | impl JsonSchema for bytes1::Bytes { 8 | fn schema_name() -> Cow<'static, str> { 9 | "Bytes".into() 10 | } 11 | 12 | fn schema_id() -> Cow<'static, str> { 13 | "bytes::Bytes".into() 14 | } 15 | 16 | fn json_schema(generator: &mut crate::SchemaGenerator) -> crate::Schema { 17 | let ty = match generator.contract() { 18 | Contract::Deserialize => Value::Array(vec!["array".into(), "string".into()]), 19 | Contract::Serialize => "array".into(), 20 | }; 21 | 22 | let mut result = Schema::default(); 23 | result.insert("type".to_owned(), ty); 24 | result.insert("items".to_owned(), generator.subschema_for::().into()); 25 | result 26 | } 27 | } 28 | 29 | forward_impl!(bytes1::BytesMut => bytes1::Bytes); 30 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/decimal.rs: -------------------------------------------------------------------------------- 1 | use crate::_alloc_prelude::*; 2 | use crate::generate::Contract; 3 | use crate::{JsonSchema, Schema, SchemaGenerator}; 4 | use alloc::borrow::Cow; 5 | use serde_json::Value; 6 | 7 | macro_rules! decimal_impl { 8 | ($type:ty) => { 9 | impl JsonSchema for $type { 10 | inline_schema!(); 11 | 12 | fn schema_name() -> Cow<'static, str> { 13 | "Decimal".into() 14 | } 15 | 16 | fn json_schema(generator: &mut SchemaGenerator) -> Schema { 17 | let (ty, pattern) = match generator.contract() { 18 | Contract::Deserialize => ( 19 | Value::Array(vec!["string".into(), "number".into()]), 20 | r"^-?\d+(\.\d+)?([eE]\d+)?$".into(), 21 | ), 22 | Contract::Serialize => ("string".into(), r"^-?\d+(\.\d+)?$".into()), 23 | }; 24 | 25 | let mut result = Schema::default(); 26 | result.insert("type".to_owned(), ty); 27 | result.insert("pattern".to_owned(), pattern); 28 | result 29 | } 30 | } 31 | }; 32 | } 33 | 34 | #[cfg(feature = "rust_decimal1")] 35 | decimal_impl!(rust_decimal1::Decimal); 36 | #[cfg(feature = "bigdecimal04")] 37 | decimal_impl!(bigdecimal04::BigDecimal); 38 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/either1.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::_alloc_prelude::*; 3 | use crate::{json_schema, JsonSchema, Schema}; 4 | use alloc::borrow::Cow; 5 | use either1::Either; 6 | 7 | impl JsonSchema for Either { 8 | inline_schema!(); 9 | 10 | fn schema_name() -> Cow<'static, str> { 11 | format!("Either_{}_or_{}", L::schema_name(), R::schema_name()).into() 12 | } 13 | 14 | fn schema_id() -> Cow<'static, str> { 15 | format!("either::Either<{}, {}>", L::schema_id(), R::schema_id()).into() 16 | } 17 | 18 | fn json_schema(generator: &mut SchemaGenerator) -> Schema { 19 | json_schema!({ 20 | "oneOf": [ 21 | { 22 | "type": "object", 23 | "properties": { 24 | "Left": generator.subschema_for::() 25 | }, 26 | "additionalProperties": false, 27 | "required": [ 28 | "Left" 29 | ] 30 | }, 31 | { 32 | "type": "object", 33 | "properties": { 34 | "Right": generator.subschema_for::() 35 | }, 36 | "additionalProperties": false, 37 | "required": [ 38 | "Right" 39 | ] 40 | } 41 | ] 42 | }) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/indexmap2.rs: -------------------------------------------------------------------------------- 1 | use crate::JsonSchema; 2 | use alloc::collections::{BTreeMap, BTreeSet}; 3 | use indexmap2::{IndexMap, IndexSet}; 4 | 5 | forward_impl!(( JsonSchema for IndexMap) => BTreeMap); 6 | forward_impl!(( JsonSchema for IndexSet) => BTreeSet); 7 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/jiff02.rs: -------------------------------------------------------------------------------- 1 | use crate::{json_schema, JsonSchema, Schema, SchemaGenerator}; 2 | use alloc::borrow::Cow; 3 | use jiff02::civil::{Date, DateTime, Time}; 4 | use jiff02::{SignedDuration, Span, Timestamp, Zoned}; 5 | 6 | macro_rules! formatted_string_impl { 7 | ($ty:ident, $format:literal) => { 8 | formatted_string_impl!($ty, $format, JsonSchema for $ty); 9 | }; 10 | ($ty:ident, $format:literal, $($desc:tt)+) => { 11 | impl $($desc)+ { 12 | inline_schema!(); 13 | 14 | fn schema_name() -> Cow<'static, str> { 15 | stringify!($ty).into() 16 | } 17 | 18 | fn schema_id() -> Cow<'static, str> { 19 | stringify!(jiff::$ty).into() 20 | } 21 | 22 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 23 | json_schema!({ 24 | "type": "string", 25 | "format": $format 26 | }) 27 | } 28 | } 29 | }; 30 | } 31 | 32 | formatted_string_impl!(SignedDuration, "duration"); 33 | formatted_string_impl!(Span, "duration"); 34 | formatted_string_impl!(Timestamp, "date-time"); 35 | formatted_string_impl!(Zoned, "zoned-date-time"); 36 | formatted_string_impl!(Date, "date"); 37 | formatted_string_impl!(Time, "partial-time"); 38 | formatted_string_impl!(DateTime, "partial-date-time"); 39 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/semver1.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::{json_schema, JsonSchema, Schema}; 3 | use alloc::borrow::Cow; 4 | use semver1::Version; 5 | 6 | impl JsonSchema for Version { 7 | fn schema_name() -> Cow<'static, str> { 8 | "SemVer".into() 9 | } 10 | 11 | fn schema_id() -> Cow<'static, str> { 12 | "semver::Version".into() 13 | } 14 | 15 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 16 | json_schema!({ 17 | "type": "string", 18 | // https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string 19 | "pattern": r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" 20 | }) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/serdejson.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::_alloc_prelude::*; 3 | use crate::{json_schema, JsonSchema, Schema}; 4 | use alloc::borrow::Cow; 5 | use alloc::collections::BTreeMap; 6 | use serde_json::{Map, Number, Value}; 7 | 8 | impl JsonSchema for Value { 9 | inline_schema!(); 10 | 11 | fn schema_name() -> Cow<'static, str> { 12 | "AnyValue".into() 13 | } 14 | 15 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 16 | true.into() 17 | } 18 | } 19 | 20 | forward_impl!(Map => BTreeMap); 21 | 22 | impl JsonSchema for Number { 23 | inline_schema!(); 24 | 25 | fn schema_name() -> Cow<'static, str> { 26 | "Number".into() 27 | } 28 | 29 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 30 | json_schema!({ 31 | "type": "number" 32 | }) 33 | } 34 | } 35 | 36 | #[cfg(feature = "raw_value")] 37 | forward_impl!(serde_json::value::RawValue => Value); 38 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/std_time.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::{json_schema, JsonSchema, Schema}; 3 | use alloc::borrow::Cow; 4 | 5 | impl JsonSchema for core::time::Duration { 6 | fn schema_name() -> Cow<'static, str> { 7 | "Duration".into() 8 | } 9 | 10 | fn schema_id() -> Cow<'static, str> { 11 | "std::time::Duration".into() 12 | } 13 | 14 | fn json_schema(generator: &mut SchemaGenerator) -> Schema { 15 | json_schema!({ 16 | "type": "object", 17 | "required": ["secs", "nanos"], 18 | "properties": { 19 | "secs": u64::json_schema(generator), 20 | "nanos": u32::json_schema(generator), 21 | } 22 | }) 23 | } 24 | } 25 | 26 | #[cfg(feature = "std")] 27 | impl JsonSchema for std::time::SystemTime { 28 | fn schema_name() -> Cow<'static, str> { 29 | "SystemTime".into() 30 | } 31 | 32 | fn schema_id() -> Cow<'static, str> { 33 | "std::time::SystemTime".into() 34 | } 35 | 36 | fn json_schema(generator: &mut SchemaGenerator) -> Schema { 37 | json_schema!({ 38 | "type": "object", 39 | "required": ["secs_since_epoch", "nanos_since_epoch"], 40 | "properties": { 41 | "secs_since_epoch": u64::json_schema(generator), 42 | "nanos_since_epoch": u32::json_schema(generator), 43 | } 44 | }) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/url2.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::{json_schema, JsonSchema, Schema}; 3 | use alloc::borrow::Cow; 4 | use url2::Url; 5 | 6 | impl JsonSchema for Url { 7 | inline_schema!(); 8 | 9 | fn schema_name() -> Cow<'static, str> { 10 | "Url".into() 11 | } 12 | 13 | fn schema_id() -> Cow<'static, str> { 14 | "url::Url".into() 15 | } 16 | 17 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 18 | json_schema!({ 19 | "type": "string", 20 | "format": "uri", 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/uuid1.rs: -------------------------------------------------------------------------------- 1 | use crate::SchemaGenerator; 2 | use crate::{json_schema, JsonSchema, Schema}; 3 | use alloc::borrow::Cow; 4 | use uuid1::Uuid; 5 | 6 | impl JsonSchema for Uuid { 7 | inline_schema!(); 8 | 9 | fn schema_name() -> Cow<'static, str> { 10 | "Uuid".into() 11 | } 12 | 13 | fn schema_id() -> Cow<'static, str> { 14 | "uuid::Uuid".into() 15 | } 16 | 17 | fn json_schema(_: &mut SchemaGenerator) -> Schema { 18 | json_schema!({ 19 | "type": "string", 20 | "format": "uuid", 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /schemars/src/json_schema_impls/wrapper.rs: -------------------------------------------------------------------------------- 1 | use crate::JsonSchema; 2 | use crate::_alloc_prelude::*; 3 | 4 | macro_rules! wrapper_impl { 5 | ($($desc:tt)+) => { 6 | forward_impl!(($($desc)+ where T: JsonSchema) => T); 7 | }; 8 | } 9 | 10 | wrapper_impl!(<'a, T: ?Sized> JsonSchema for &'a T); 11 | wrapper_impl!(<'a, T: ?Sized> JsonSchema for &'a mut T); 12 | wrapper_impl!( JsonSchema for Box); 13 | wrapper_impl!( JsonSchema for alloc::rc::Rc); 14 | wrapper_impl!( JsonSchema for alloc::rc::Weak); 15 | wrapper_impl!( JsonSchema for alloc::sync::Arc); 16 | wrapper_impl!( JsonSchema for alloc::sync::Weak); 17 | #[cfg(feature = "std")] 18 | wrapper_impl!( JsonSchema for std::sync::Mutex); 19 | #[cfg(feature = "std")] 20 | wrapper_impl!( JsonSchema for std::sync::RwLock); 21 | wrapper_impl!( JsonSchema for core::cell::Cell); 22 | wrapper_impl!( JsonSchema for core::cell::RefCell); 23 | wrapper_impl!(<'a, T: ?Sized + ToOwned> JsonSchema for alloc::borrow::Cow<'a, T>); 24 | wrapper_impl!( JsonSchema for core::num::Wrapping); 25 | wrapper_impl!( JsonSchema for core::cmp::Reverse); 26 | -------------------------------------------------------------------------------- /schemars/tests/integration/arrayvec.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use arrayvec07::{ArrayString, ArrayVec}; 3 | 4 | #[test] 5 | fn arrayvec07() { 6 | test!(ArrayVec) 7 | .assert_snapshot() 8 | .assert_allows_ser_roundtrip([ 9 | ArrayVec::from_iter([]), 10 | ArrayVec::from_iter([1, 2, 3, 4, 5, 6, 7, 8]), 11 | ]) 12 | .assert_matches_de_roundtrip( 13 | (0..16).map(|len| Value::Array((0..len).map(Value::from).collect())), 14 | ) 15 | .assert_matches_de_roundtrip(arbitrary_values_except( 16 | is_array_of_u64, 17 | "FIXME schema allows out-of-range positive integers", 18 | )); 19 | } 20 | 21 | #[test] 22 | fn arrayvec07_arraystring() { 23 | test!(ArrayString<8>) 24 | .assert_identical::() 25 | .assert_allows_ser_roundtrip(["".try_into().unwrap(), "12345678".try_into().unwrap()]) 26 | .assert_matches_de_roundtrip(arbitrary_values_except( 27 | Value::is_string, 28 | "There's not a good way to express UTF-8 byte length in JSON schema, so schema ignores the ArrayString's capacity.", 29 | )); 30 | } 31 | 32 | fn is_array_of_u64(value: &Value) -> bool { 33 | value 34 | .as_array() 35 | .is_some_and(|a| a.iter().all(Value::is_u64)) 36 | } 37 | -------------------------------------------------------------------------------- /schemars/tests/integration/bound.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use std::marker::PhantomData; 3 | 4 | struct MyIterator; 5 | 6 | impl Iterator for MyIterator { 7 | type Item = String; 8 | 9 | fn next(&mut self) -> Option { 10 | unimplemented!() 11 | } 12 | } 13 | 14 | // The default trait bounds would require T to implement JsonSchema, which MyIterator does not. 15 | // Ideally we wouldn't need the `bound` attribute here at all - it should be possible to better 16 | // infer automatic trait bounds (tracked in https://github.com/GREsau/schemars/issues/168) 17 | #[derive(JsonSchema, Serialize, Deserialize)] 18 | #[schemars(bound = "T::Item: JsonSchema")] 19 | pub struct MyContainer 20 | where 21 | T: Iterator, 22 | { 23 | pub associated: T::Item, 24 | pub generic: PhantomData, 25 | } 26 | 27 | #[test] 28 | fn manual_bound_set() { 29 | test!(MyContainer) 30 | .assert_snapshot() 31 | .assert_allows_ser_roundtrip([MyContainer { 32 | associated: "test".to_owned(), 33 | generic: PhantomData, 34 | }]) 35 | .assert_matches_de_roundtrip(arbitrary_values()); 36 | } 37 | -------------------------------------------------------------------------------- /schemars/tests/integration/bytes.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use bytes1::{Bytes, BytesMut}; 3 | 4 | #[test] 5 | fn bytes() { 6 | test!(Bytes) 7 | .assert_snapshot() 8 | .assert_allows_ser_roundtrip([Bytes::new(), Bytes::from_iter([12; 34])]) 9 | .assert_matches_de_roundtrip(arbitrary_values()); 10 | } 11 | 12 | #[test] 13 | fn bytes_mut() { 14 | test!(BytesMut).assert_identical::(); 15 | } 16 | -------------------------------------------------------------------------------- /schemars/tests/integration/chrono.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use chrono04::prelude::*; 3 | 4 | #[derive(JsonSchema, Serialize, Deserialize)] 5 | struct ChronoTypes { 6 | weekday: Weekday, 7 | date_time: DateTime, 8 | naive_date: NaiveDate, 9 | naive_date_time: NaiveDateTime, 10 | naive_time: NaiveTime, 11 | } 12 | 13 | #[test] 14 | fn chrono() { 15 | test!(ChronoTypes).assert_snapshot(); 16 | 17 | test!(Weekday) 18 | .assert_allows_ser_roundtrip([Weekday::Mon]) 19 | .assert_matches_de_roundtrip(arbitrary_values()); 20 | 21 | test!(DateTime) 22 | .assert_allows_ser_roundtrip_default() 23 | .assert_matches_de_roundtrip(arbitrary_values()); 24 | 25 | test!(NaiveDate) 26 | .assert_allows_ser_roundtrip_default() 27 | .assert_matches_de_roundtrip(arbitrary_values()); 28 | 29 | test!(NaiveDateTime) 30 | .assert_allows_ser_roundtrip_default() 31 | .assert_matches_de_roundtrip(arbitrary_values_except( 32 | Value::is_string, 33 | "Custom format 'partial-date-time', so arbitrary strings technically allowed by schema", 34 | )); 35 | 36 | test!(NaiveTime) 37 | .assert_allows_ser_roundtrip_default() 38 | .assert_matches_de_roundtrip(arbitrary_values_except( 39 | Value::is_string, 40 | "Custom format 'date-time', so arbitrary strings technically allowed by schema", 41 | )); 42 | } 43 | -------------------------------------------------------------------------------- /schemars/tests/integration/crate_alias.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use ::schemars as aliased_schemars; 3 | 4 | #[allow(dead_code)] 5 | #[derive(aliased_schemars::JsonSchema, Deserialize, Serialize, Default)] 6 | #[schemars(crate = "aliased_schemars")] 7 | struct MyStruct { 8 | /// Is it ok with doc comments? 9 | foo: i32, 10 | #[schemars(extend("x-test" = "...and extensions?"))] 11 | bar: bool, 12 | } 13 | 14 | #[test] 15 | fn crate_alias() { 16 | test!(MyStruct) 17 | .assert_allows_ser_roundtrip_default() 18 | .assert_matches_de_roundtrip(arbitrary_values()); 19 | } 20 | -------------------------------------------------------------------------------- /schemars/tests/integration/decimal.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | #[test] 4 | fn decimal_types() { 5 | #[cfg(feature = "rust_decimal1")] 6 | test!(rust_decimal1::Decimal) 7 | .assert_snapshot() 8 | .assert_allows_ser_roundtrip_default() 9 | .assert_matches_de_roundtrip(arbitrary_values()); 10 | 11 | #[cfg(feature = "bigdecimal04")] 12 | test!(bigdecimal04::BigDecimal) 13 | .assert_snapshot() 14 | .assert_allows_ser_roundtrip_default() 15 | .assert_matches_de_roundtrip(arbitrary_values()); 16 | 17 | #[cfg(all(feature = "rust_decimal1", feature = "bigdecimal04"))] 18 | test!(bigdecimal04::BigDecimal).assert_identical::(); 19 | } 20 | -------------------------------------------------------------------------------- /schemars/tests/integration/either.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use either1::Either; 3 | 4 | #[test] 5 | fn either() { 6 | test!(Either>) 7 | .assert_snapshot() 8 | .assert_allows_ser_roundtrip([ 9 | Either::Left(123), 10 | Either::Right(Either::Left(true)), 11 | Either::Right(Either::Right(())), 12 | ]) 13 | .assert_matches_de_roundtrip(arbitrary_values()); 14 | } 15 | -------------------------------------------------------------------------------- /schemars/tests/integration/enum_repr.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use schemars::JsonSchema_repr; 3 | use serde_repr::{Deserialize_repr, Serialize_repr}; 4 | 5 | #[derive(JsonSchema_repr, Deserialize_repr, Serialize_repr)] 6 | #[repr(u8)] 7 | #[serde(rename = "EnumWithReprAttr")] 8 | /// Description from comment 9 | pub enum Enum { 10 | Zero, 11 | One, 12 | Five = 5, 13 | Six, 14 | Three = 3, 15 | } 16 | 17 | #[test] 18 | fn enum_repr() { 19 | test!(Enum) 20 | .assert_snapshot() 21 | .assert_allows_ser_roundtrip([Enum::Zero, Enum::One, Enum::Five, Enum::Six, Enum::Three]) 22 | .assert_allows_de_roundtrip([ 23 | Value::from(0), 24 | Value::from(1), 25 | Value::from(5), 26 | Value::from(6), 27 | Value::from(3), 28 | ]) 29 | .assert_rejects_de([ 30 | Value::from("Zero"), 31 | Value::from("One"), 32 | Value::from("Five"), 33 | Value::from("Six"), 34 | Value::from("Three"), 35 | ]) 36 | .assert_matches_de_roundtrip(arbitrary_values()); 37 | } 38 | -------------------------------------------------------------------------------- /schemars/tests/integration/examples.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | #[derive(Default, JsonSchema, Serialize)] 4 | #[schemars(example = Struct::default(), example = ())] 5 | struct Struct { 6 | #[schemars(example = 4 + 4, example = ())] 7 | foo: i32, 8 | bar: bool, 9 | #[schemars(example = (), example = &"foo")] 10 | baz: Option<&'static str>, 11 | } 12 | 13 | #[test] 14 | fn examples() { 15 | test!(Struct).assert_snapshot(); 16 | } 17 | -------------------------------------------------------------------------------- /schemars/tests/integration/indexmap.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use indexmap2::{indexmap, indexset, IndexMap, IndexSet}; 3 | use std::collections::{BTreeMap, BTreeSet}; 4 | 5 | #[test] 6 | fn indexmap() { 7 | test!(IndexMap) 8 | .assert_identical::>() 9 | .assert_allows_ser_roundtrip([indexmap!(), indexmap!("key".to_owned() => true)]) 10 | .assert_matches_de_roundtrip(arbitrary_values()); 11 | } 12 | 13 | #[test] 14 | fn indexset() { 15 | test!(IndexSet) 16 | .assert_identical::>() 17 | .assert_allows_ser_roundtrip([indexset!(), indexset!("test".to_owned())]) 18 | .assert_matches_de_roundtrip(arbitrary_values()); 19 | } 20 | -------------------------------------------------------------------------------- /schemars/tests/integration/macros.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | macro_rules! build_struct { 4 | ( 5 | $id:ident { $($t:tt)* } 6 | ) => { 7 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 8 | pub struct $id { 9 | x: u8, 10 | $($t)* 11 | } 12 | }; 13 | } 14 | 15 | build_struct!(A { v: i32 }); 16 | 17 | #[test] 18 | fn macro_built_struct() { 19 | test!(A).assert_allows_ser_roundtrip_default(); 20 | } 21 | 22 | macro_rules! build_enum { 23 | ( 24 | $(#[$outer_derive:meta])* 25 | $outer:ident { 26 | $($(#[$inner_derive:meta])* 27 | $inner:ident { 28 | $( $(#[$field_attribute:meta])* 29 | $field:ident : $ty:ty),* 30 | })* 31 | } 32 | ) => { 33 | 34 | $( 35 | $(#[$inner_derive])* 36 | pub struct $inner { 37 | $( 38 | $(#[$field_attribute])* 39 | pub $field: $ty 40 | ),* 41 | } 42 | )* 43 | 44 | $(#[$outer_derive])* 45 | pub enum $outer { 46 | $( 47 | $inner($inner) 48 | ),* 49 | } 50 | } 51 | } 52 | 53 | build_enum!( 54 | #[derive(JsonSchema, Deserialize, Serialize)] 55 | OuterEnum { 56 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 57 | InnerStruct { 58 | x: i32 59 | } 60 | } 61 | 62 | ); 63 | 64 | #[test] 65 | fn macro_built_enum() { 66 | test!(OuterEnum).assert_allows_ser_roundtrip([OuterEnum::InnerStruct(InnerStruct::default())]); 67 | } 68 | -------------------------------------------------------------------------------- /schemars/tests/integration/map.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use std::collections::{BTreeMap, HashMap}; 3 | 4 | #[derive(JsonSchema, Deserialize, Serialize, Default, PartialEq, Eq, PartialOrd, Ord)] 5 | #[schemars(extend("pattern" = "^[0-9a-f]*$"))] 6 | struct HexNumber(String); 7 | 8 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 9 | struct Maps { 10 | s_map: HashMap, 11 | i_map: BTreeMap, 12 | u_map: HashMap, 13 | pattern_map: BTreeMap, 14 | } 15 | 16 | #[test] 17 | fn maps() { 18 | test!(Maps) 19 | .assert_snapshot() 20 | .assert_allows_ser_roundtrip([Maps { 21 | s_map: HashMap::from_iter([("test".to_owned(), true)]), 22 | i_map: BTreeMap::from_iter([(-123, true), (123, true)]), 23 | u_map: HashMap::from_iter([(123, true)]), 24 | pattern_map: BTreeMap::from_iter([(HexNumber("b4df00d".to_owned()), true)]), 25 | }]) 26 | .assert_matches_de_roundtrip(arbitrary_values()); 27 | } 28 | -------------------------------------------------------------------------------- /schemars/tests/integration/same_name.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | mod a { 4 | use super::*; 5 | 6 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 7 | pub struct Config { 8 | test: String, 9 | } 10 | } 11 | 12 | mod b { 13 | use super::*; 14 | 15 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 16 | pub struct Config { 17 | test2: String, 18 | } 19 | } 20 | 21 | mod c { 22 | use super::*; 23 | 24 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 25 | #[schemars(rename = "Config")] 26 | pub struct Configuration { 27 | test3: String, 28 | } 29 | } 30 | 31 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 32 | pub struct Config2 { 33 | a_cfg: a::Config, 34 | b_cfg: b::Config, 35 | c_cfg: c::Configuration, 36 | } 37 | 38 | #[test] 39 | fn same_name() { 40 | test!(Config2) 41 | .assert_snapshot() 42 | .assert_allows_ser_roundtrip_default() 43 | .assert_matches_de_roundtrip(arbitrary_values()); 44 | } 45 | -------------------------------------------------------------------------------- /schemars/tests/integration/schema_with.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 4 | struct Struct { 5 | #[serde(with = "int_as_str")] 6 | #[schemars(schema_with = "int_as_str::json_schema")] 7 | x: i64, 8 | } 9 | 10 | mod int_as_str { 11 | pub(super) fn serialize(value: &T, ser: S) -> Result 12 | where 13 | S: serde::Serializer, 14 | T: std::fmt::Display, 15 | { 16 | ser.collect_str(value) 17 | } 18 | 19 | pub(super) fn deserialize<'de, D, T>(deser: D) -> Result 20 | where 21 | D: serde::Deserializer<'de>, 22 | T: std::str::FromStr, 23 | { 24 | <&str as serde::Deserialize>::deserialize(deser)? 25 | .parse() 26 | .map_err(serde::de::Error::custom) 27 | } 28 | 29 | pub(super) fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { 30 | schemars::json_schema!({ 31 | "type": "string", 32 | "pattern": r"^-?\d+$" 33 | }) 34 | } 35 | } 36 | 37 | #[test] 38 | fn schema_with() { 39 | test!(Struct) 40 | .assert_snapshot() 41 | .assert_allows_ser_roundtrip_default() 42 | .assert_matches_de_roundtrip(arbitrary_values_except( 43 | Value::is_array, 44 | "structs with `#derive(Deserialize)` can technically be deserialized from sequences, but that's not intended to be used via JSON, so schemars ignores it", 45 | )); 46 | } 47 | -------------------------------------------------------------------------------- /schemars/tests/integration/semver.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use semver1::Version; 3 | 4 | #[test] 5 | fn semver() { 6 | test!(Version) 7 | .assert_snapshot() 8 | .assert_allows_de_roundtrip( 9 | [ 10 | "1.2.3", 11 | "1.2.3-alpha4", 12 | "1.2.3+build4", 13 | "1.2.3+04", 14 | "1.2.3-1.alpha.2+5.build.4.3-21", 15 | ] 16 | .into_iter() 17 | .map(Value::from), 18 | ) 19 | .assert_rejects_de( 20 | [ 21 | "1.2", 22 | "1.2.3.4", 23 | "1.2.03", 24 | "1.2.3-alpha..", 25 | "1.2.3-alpha.04", 26 | "1.2.3++", 27 | ] 28 | .into_iter() 29 | .map(Value::from), 30 | ) 31 | .assert_matches_de_roundtrip(arbitrary_values()); 32 | } 33 | -------------------------------------------------------------------------------- /schemars/tests/integration/skip.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | #[derive(JsonSchema, Deserialize, Serialize)] 4 | #[serde(deny_unknown_fields)] 5 | struct Struct { 6 | #[serde(skip)] 7 | _skipped: bool, 8 | included: bool, 9 | } 10 | 11 | #[test] 12 | fn skip_struct_field() { 13 | test!(Struct) 14 | .assert_snapshot() 15 | .assert_allows_de_roundtrip([json!({ "included": true })]) 16 | .assert_rejects_de([json!({ 17 | "_skipped": true, 18 | "included": true 19 | })]) 20 | .assert_matches_de_roundtrip(arbitrary_values_except( 21 | Value::is_array, 22 | "structs with `#derive(Deserialize)` can technically be deserialized from sequences, but that's not intended to be used via JSON, so schemars ignores it", 23 | )); 24 | } 25 | 26 | #[derive(JsonSchema, Deserialize, Serialize)] 27 | pub enum Enum { 28 | Included1, 29 | #[serde(skip)] 30 | _Skipped, 31 | Included2, 32 | } 33 | 34 | #[test] 35 | fn skip_enum_variants() { 36 | test!(Enum) 37 | .assert_snapshot() 38 | .assert_allows_de_roundtrip([json!("Included1"), json!("Included2")]) 39 | .assert_rejects_de([json!("_Skipped")]) 40 | .assert_matches_de_roundtrip(arbitrary_values()); 41 | } 42 | -------------------------------------------------------------------------------- /schemars/tests/integration/smallvec.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use smallvec1::{smallvec, SmallVec}; 3 | 4 | #[test] 5 | fn smallvec() { 6 | test!(SmallVec<[usize; 2]>) 7 | .assert_identical::>() 8 | .assert_allows_ser_roundtrip([smallvec![], smallvec![1, 2, 3, 4, 5]]) 9 | .assert_matches_de_roundtrip(arbitrary_values()); 10 | } 11 | -------------------------------------------------------------------------------- /schemars/tests/integration/smol_str.rs: -------------------------------------------------------------------------------- 1 | use smol_str02::SmolStr; 2 | 3 | use crate::prelude::*; 4 | 5 | #[test] 6 | fn smol_str() { 7 | test!(SmolStr) 8 | .assert_identical::() 9 | .assert_allows_ser_roundtrip(["".into(), "test".into()]) 10 | .assert_matches_de_roundtrip(arbitrary_values()); 11 | } 12 | -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/arrayvec.rs~arrayvec07.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Array_up_to_size_8_of_int32", 4 | "type": "array", 5 | "items": { 6 | "type": "integer", 7 | "format": "int32" 8 | }, 9 | "maxItems": 8 10 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/bound.rs~manual_bound_set.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyContainer_for_T", 4 | "type": "object", 5 | "properties": { 6 | "associated": { 7 | "type": "string" 8 | }, 9 | "generic": { 10 | "type": "null" 11 | } 12 | }, 13 | "required": [ 14 | "associated", 15 | "generic" 16 | ] 17 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/bytes.rs~bytes.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Bytes", 4 | "type": [ 5 | "array", 6 | "string" 7 | ], 8 | "items": { 9 | "type": "integer", 10 | "format": "uint8", 11 | "minimum": 0, 12 | "maximum": 255 13 | } 14 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/bytes.rs~bytes.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Bytes", 4 | "type": "array", 5 | "items": { 6 | "type": "integer", 7 | "format": "uint8", 8 | "minimum": 0, 9 | "maximum": 255 10 | } 11 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/chrono.rs~chrono.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "ChronoTypes", 4 | "type": "object", 5 | "properties": { 6 | "weekday": { 7 | "type": "string", 8 | "enum": [ 9 | "Mon", 10 | "Tue", 11 | "Wed", 12 | "Thu", 13 | "Fri", 14 | "Sat", 15 | "Sun" 16 | ] 17 | }, 18 | "date_time": { 19 | "type": "string", 20 | "format": "date-time" 21 | }, 22 | "naive_date": { 23 | "type": "string", 24 | "format": "date" 25 | }, 26 | "naive_date_time": { 27 | "type": "string", 28 | "format": "partial-date-time" 29 | }, 30 | "naive_time": { 31 | "type": "string", 32 | "format": "partial-time" 33 | } 34 | }, 35 | "required": [ 36 | "weekday", 37 | "date_time", 38 | "naive_date", 39 | "naive_date_time", 40 | "naive_time" 41 | ] 42 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~adjacently_tagged_enum.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "AdjacentEnum", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "tag": { 9 | "type": "string", 10 | "const": "WriteOnlyUnit" 11 | } 12 | }, 13 | "required": [ 14 | "tag" 15 | ] 16 | }, 17 | { 18 | "type": "object", 19 | "properties": { 20 | "tag": { 21 | "type": "string", 22 | "const": "WriteOnlyStruct" 23 | }, 24 | "content": { 25 | "type": "object", 26 | "properties": { 27 | "i": { 28 | "type": "integer", 29 | "format": "int" 30 | } 31 | }, 32 | "required": [ 33 | "i" 34 | ] 35 | } 36 | }, 37 | "required": [ 38 | "tag", 39 | "content" 40 | ] 41 | }, 42 | { 43 | "type": "object", 44 | "properties": { 45 | "tag": { 46 | "type": "string", 47 | "const": "de_renamed_unit" 48 | } 49 | }, 50 | "required": [ 51 | "tag" 52 | ] 53 | }, 54 | { 55 | "type": "object", 56 | "properties": { 57 | "tag": { 58 | "type": "string", 59 | "const": "de_renamed_struct" 60 | }, 61 | "content": { 62 | "type": "object", 63 | "properties": { 64 | "b": { 65 | "type": "boolean" 66 | } 67 | }, 68 | "required": [ 69 | "b" 70 | ] 71 | } 72 | }, 73 | "required": [ 74 | "tag", 75 | "content" 76 | ] 77 | } 78 | ] 79 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~adjacently_tagged_enum.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "AdjacentEnum", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "tag": { 9 | "type": "string", 10 | "const": "READ-ONLY-UNIT" 11 | } 12 | }, 13 | "required": [ 14 | "tag" 15 | ] 16 | }, 17 | { 18 | "type": "object", 19 | "properties": { 20 | "tag": { 21 | "type": "string", 22 | "const": "READ-ONLY-STRUCT" 23 | }, 24 | "content": { 25 | "type": "object", 26 | "properties": { 27 | "S": { 28 | "type": "string" 29 | } 30 | }, 31 | "required": [ 32 | "S" 33 | ] 34 | } 35 | }, 36 | "required": [ 37 | "tag", 38 | "content" 39 | ] 40 | }, 41 | { 42 | "type": "object", 43 | "properties": { 44 | "tag": { 45 | "type": "string", 46 | "const": "ser_renamed_unit" 47 | } 48 | }, 49 | "required": [ 50 | "tag" 51 | ] 52 | }, 53 | { 54 | "type": "object", 55 | "properties": { 56 | "tag": { 57 | "type": "string", 58 | "const": "ser_renamed_struct" 59 | }, 60 | "content": { 61 | "type": "object", 62 | "properties": { 63 | "B": { 64 | "type": "boolean" 65 | } 66 | }, 67 | "required": [ 68 | "B" 69 | ] 70 | } 71 | }, 72 | "required": [ 73 | "tag", 74 | "content" 75 | ] 76 | } 77 | ] 78 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~externally_tagged_enum.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "ExternalEnum", 4 | "oneOf": [ 5 | { 6 | "type": "string", 7 | "enum": [ 8 | "WriteOnlyUnit", 9 | "de_renamed_unit" 10 | ] 11 | }, 12 | { 13 | "type": "object", 14 | "properties": { 15 | "WriteOnlyStruct": { 16 | "type": "object", 17 | "properties": { 18 | "i": { 19 | "type": "integer", 20 | "format": "int" 21 | } 22 | }, 23 | "required": [ 24 | "i" 25 | ] 26 | } 27 | }, 28 | "required": [ 29 | "WriteOnlyStruct" 30 | ], 31 | "additionalProperties": false 32 | }, 33 | { 34 | "type": "object", 35 | "properties": { 36 | "de_renamed_struct": { 37 | "type": "object", 38 | "properties": { 39 | "b": { 40 | "type": "boolean" 41 | } 42 | }, 43 | "required": [ 44 | "b" 45 | ] 46 | } 47 | }, 48 | "required": [ 49 | "de_renamed_struct" 50 | ], 51 | "additionalProperties": false 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~externally_tagged_enum.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "ExternalEnum", 4 | "oneOf": [ 5 | { 6 | "type": "string", 7 | "enum": [ 8 | "READ-ONLY-UNIT", 9 | "ser_renamed_unit" 10 | ] 11 | }, 12 | { 13 | "type": "object", 14 | "properties": { 15 | "READ-ONLY-STRUCT": { 16 | "type": "object", 17 | "properties": { 18 | "S": { 19 | "type": "string" 20 | } 21 | }, 22 | "required": [ 23 | "S" 24 | ] 25 | } 26 | }, 27 | "required": [ 28 | "READ-ONLY-STRUCT" 29 | ], 30 | "additionalProperties": false 31 | }, 32 | { 33 | "type": "object", 34 | "properties": { 35 | "ser_renamed_struct": { 36 | "type": "object", 37 | "properties": { 38 | "B": { 39 | "type": "boolean" 40 | } 41 | }, 42 | "required": [ 43 | "B" 44 | ] 45 | } 46 | }, 47 | "required": [ 48 | "ser_renamed_struct" 49 | ], 50 | "additionalProperties": false 51 | } 52 | ] 53 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~internally_tagged_enum.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "InternalEnum", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "tag": { 9 | "type": "string", 10 | "const": "WriteOnlyUnit" 11 | } 12 | }, 13 | "required": [ 14 | "tag" 15 | ] 16 | }, 17 | { 18 | "type": "object", 19 | "properties": { 20 | "i": { 21 | "type": "integer", 22 | "format": "int" 23 | }, 24 | "tag": { 25 | "type": "string", 26 | "const": "WriteOnlyStruct" 27 | } 28 | }, 29 | "required": [ 30 | "tag", 31 | "i" 32 | ] 33 | }, 34 | { 35 | "type": "object", 36 | "properties": { 37 | "tag": { 38 | "type": "string", 39 | "const": "de_renamed_unit" 40 | } 41 | }, 42 | "required": [ 43 | "tag" 44 | ] 45 | }, 46 | { 47 | "type": "object", 48 | "properties": { 49 | "b": { 50 | "type": "boolean" 51 | }, 52 | "tag": { 53 | "type": "string", 54 | "const": "de_renamed_struct" 55 | } 56 | }, 57 | "required": [ 58 | "tag", 59 | "b" 60 | ] 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~internally_tagged_enum.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "InternalEnum", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "tag": { 9 | "type": "string", 10 | "const": "READ-ONLY-UNIT" 11 | } 12 | }, 13 | "required": [ 14 | "tag" 15 | ] 16 | }, 17 | { 18 | "type": "object", 19 | "properties": { 20 | "S": { 21 | "type": "string" 22 | }, 23 | "tag": { 24 | "type": "string", 25 | "const": "READ-ONLY-STRUCT" 26 | } 27 | }, 28 | "required": [ 29 | "tag", 30 | "S" 31 | ] 32 | }, 33 | { 34 | "type": "object", 35 | "properties": { 36 | "tag": { 37 | "type": "string", 38 | "const": "ser_renamed_unit" 39 | } 40 | }, 41 | "required": [ 42 | "tag" 43 | ] 44 | }, 45 | { 46 | "type": "object", 47 | "properties": { 48 | "B": { 49 | "type": "boolean" 50 | }, 51 | "tag": { 52 | "type": "string", 53 | "const": "ser_renamed_struct" 54 | } 55 | }, 56 | "required": [ 57 | "tag", 58 | "B" 59 | ] 60 | } 61 | ] 62 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~struct_allow_unknown_fields.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "StructAllowUnknownFields", 4 | "type": "object", 5 | "properties": { 6 | "write_only": { 7 | "type": "boolean", 8 | "writeOnly": true 9 | }, 10 | "default": { 11 | "type": "boolean", 12 | "default": false 13 | }, 14 | "skip_serializing_if": { 15 | "type": "boolean" 16 | }, 17 | "de_renamed": { 18 | "type": "boolean" 19 | }, 20 | "option": { 21 | "type": [ 22 | "boolean", 23 | "null" 24 | ] 25 | } 26 | }, 27 | "required": [ 28 | "write_only", 29 | "skip_serializing_if", 30 | "de_renamed" 31 | ] 32 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~struct_allow_unknown_fields.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "StructAllowUnknownFields", 4 | "type": "object", 5 | "properties": { 6 | "READ-ONLY": { 7 | "type": "boolean", 8 | "readOnly": true, 9 | "default": false 10 | }, 11 | "DEFAULT": { 12 | "type": "boolean", 13 | "default": false 14 | }, 15 | "SKIP-SERIALIZING-IF": { 16 | "type": "boolean" 17 | }, 18 | "ser_renamed": { 19 | "type": "boolean" 20 | }, 21 | "OPTION": { 22 | "type": [ 23 | "boolean", 24 | "null" 25 | ] 26 | } 27 | }, 28 | "required": [ 29 | "READ-ONLY", 30 | "DEFAULT", 31 | "ser_renamed", 32 | "OPTION" 33 | ] 34 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~struct_deny_unknown_fields.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "StructDenyUnknownFields", 4 | "type": "object", 5 | "properties": { 6 | "write_only": { 7 | "type": "boolean", 8 | "writeOnly": true 9 | }, 10 | "default": { 11 | "type": "boolean", 12 | "default": false 13 | }, 14 | "skip_serializing_if": { 15 | "type": "boolean" 16 | }, 17 | "de_renamed": { 18 | "type": "boolean" 19 | }, 20 | "option": { 21 | "type": [ 22 | "boolean", 23 | "null" 24 | ] 25 | } 26 | }, 27 | "additionalProperties": false, 28 | "required": [ 29 | "write_only", 30 | "skip_serializing_if", 31 | "de_renamed" 32 | ] 33 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~struct_deny_unknown_fields.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "StructDenyUnknownFields", 4 | "type": "object", 5 | "properties": { 6 | "READ-ONLY": { 7 | "type": "boolean", 8 | "readOnly": true, 9 | "default": false 10 | }, 11 | "DEFAULT": { 12 | "type": "boolean", 13 | "default": false 14 | }, 15 | "SKIP-SERIALIZING-IF": { 16 | "type": "boolean" 17 | }, 18 | "ser_renamed": { 19 | "type": "boolean" 20 | }, 21 | "OPTION": { 22 | "type": [ 23 | "boolean", 24 | "null" 25 | ] 26 | } 27 | }, 28 | "additionalProperties": false, 29 | "required": [ 30 | "READ-ONLY", 31 | "DEFAULT", 32 | "ser_renamed", 33 | "OPTION" 34 | ] 35 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~tuple_struct.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TupleStruct", 4 | "type": "array", 5 | "prefixItems": [ 6 | { 7 | "type": "string" 8 | }, 9 | { 10 | "type": "boolean", 11 | "writeOnly": true 12 | }, 13 | { 14 | "type": "string" 15 | }, 16 | { 17 | "type": "string" 18 | } 19 | ], 20 | "minItems": 4, 21 | "maxItems": 4 22 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~tuple_struct.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TupleStruct", 4 | "type": "array", 5 | "prefixItems": [ 6 | { 7 | "type": "string" 8 | }, 9 | { 10 | "type": "string" 11 | }, 12 | { 13 | "type": "boolean", 14 | "readOnly": true 15 | }, 16 | { 17 | "type": "string" 18 | } 19 | ], 20 | "minItems": 4, 21 | "maxItems": 4 22 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~untagged_enum.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "UntaggedEnum", 4 | "anyOf": [ 5 | { 6 | "type": "null" 7 | }, 8 | { 9 | "type": "object", 10 | "properties": { 11 | "i": { 12 | "type": "integer", 13 | "format": "int" 14 | } 15 | }, 16 | "required": [ 17 | "i" 18 | ] 19 | }, 20 | { 21 | "type": "null" 22 | }, 23 | { 24 | "type": "object", 25 | "properties": { 26 | "b": { 27 | "type": "boolean" 28 | } 29 | }, 30 | "required": [ 31 | "b" 32 | ] 33 | } 34 | ] 35 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/contract.rs~untagged_enum.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "UntaggedEnum", 4 | "anyOf": [ 5 | { 6 | "type": "null" 7 | }, 8 | { 9 | "type": "object", 10 | "properties": { 11 | "S": { 12 | "type": "string" 13 | } 14 | }, 15 | "required": [ 16 | "S" 17 | ] 18 | }, 19 | { 20 | "type": "null" 21 | }, 22 | { 23 | "type": "object", 24 | "properties": { 25 | "B": { 26 | "type": "boolean" 27 | } 28 | }, 29 | "required": [ 30 | "B" 31 | ] 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/decimal.rs~decimal_types.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Decimal", 4 | "type": [ 5 | "string", 6 | "number" 7 | ], 8 | "pattern": "^-?\\d+(\\.\\d+)?([eE]\\d+)?$" 9 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/decimal.rs~decimal_types.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Decimal", 4 | "type": "string", 5 | "pattern": "^-?\\d+(\\.\\d+)?$" 6 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/default.rs~default_fields.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "integer": { 7 | "type": "integer", 8 | "format": "uint32", 9 | "minimum": 0, 10 | "default": 0 11 | }, 12 | "boolean": { 13 | "type": "boolean", 14 | "default": false 15 | }, 16 | "option_string": { 17 | "type": [ 18 | "string", 19 | "null" 20 | ], 21 | "default": null 22 | }, 23 | "string_skip_empty": { 24 | "type": "string" 25 | }, 26 | "struct2": { 27 | "type": "string", 28 | "pattern": "^\\d+ (true|false)$", 29 | "default": "0 false" 30 | }, 31 | "not_serialize": { 32 | "$ref": "#/$defs/NotSerialize", 33 | "writeOnly": true 34 | } 35 | }, 36 | "$defs": { 37 | "NotSerialize": { 38 | "type": "integer", 39 | "format": "int8", 40 | "minimum": -128, 41 | "maximum": 127 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/default.rs~default_fields.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "integer": { 7 | "type": "integer", 8 | "format": "uint32", 9 | "minimum": 0, 10 | "default": 0 11 | }, 12 | "boolean": { 13 | "type": "boolean", 14 | "default": false 15 | }, 16 | "option_string": { 17 | "type": [ 18 | "string", 19 | "null" 20 | ], 21 | "default": null 22 | }, 23 | "string_skip_empty": { 24 | "type": "string" 25 | }, 26 | "struct2": { 27 | "type": "string", 28 | "pattern": "^\\d+ (true|false)$", 29 | "default": "0 false" 30 | } 31 | }, 32 | "required": [ 33 | "integer", 34 | "boolean", 35 | "option_string", 36 | "struct2" 37 | ] 38 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/deprecated.rs~deprecated_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "DeprecatedEnum", 4 | "oneOf": [ 5 | { 6 | "type": "string", 7 | "enum": [ 8 | "Unit" 9 | ] 10 | }, 11 | { 12 | "type": "string", 13 | "const": "DeprecatedUnitVariant", 14 | "deprecated": true 15 | }, 16 | { 17 | "type": "object", 18 | "properties": { 19 | "DeprecatedStructVariant": { 20 | "type": "object", 21 | "properties": { 22 | "foo": { 23 | "type": "integer", 24 | "format": "int32" 25 | }, 26 | "deprecated_field": { 27 | "type": "boolean", 28 | "deprecated": true 29 | } 30 | }, 31 | "required": [ 32 | "foo", 33 | "deprecated_field" 34 | ] 35 | } 36 | }, 37 | "required": [ 38 | "DeprecatedStructVariant" 39 | ], 40 | "additionalProperties": false, 41 | "deprecated": true 42 | } 43 | ], 44 | "deprecated": true 45 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/deprecated.rs~deprecated_struct.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "DeprecatedStruct", 4 | "type": "object", 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "format": "int32" 9 | }, 10 | "bar": { 11 | "type": "boolean", 12 | "deprecated": true 13 | } 14 | }, 15 | "required": [ 16 | "foo", 17 | "bar" 18 | ], 19 | "deprecated": true 20 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/docs.rs~doc_comments_enum.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "This is the enum's title", 4 | "description": "This is \nthe enum's description.", 5 | "oneOf": [ 6 | { 7 | "type": "string", 8 | "enum": [ 9 | "UndocumentedUnit", 10 | "UndocumentedUnit2" 11 | ] 12 | }, 13 | { 14 | "description": "This comment is included in the generated schema :)", 15 | "type": "string", 16 | "const": "DocumentedUnit" 17 | }, 18 | { 19 | "title": "Complex variant", 20 | "description": "This is a struct-like variant.", 21 | "type": "object", 22 | "properties": { 23 | "Complex": { 24 | "type": "object", 25 | "properties": { 26 | "my_nullable_string": { 27 | "title": "A nullable string", 28 | "description": "This field is a nullable string.\n\nThis\nis\n the second\n line!\n\n\n\n\nAnd this is the third!", 29 | "type": [ 30 | "string", 31 | "null" 32 | ] 33 | } 34 | } 35 | } 36 | }, 37 | "required": [ 38 | "Complex" 39 | ], 40 | "additionalProperties": false 41 | } 42 | ] 43 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/docs.rs~doc_comments_enum.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "This is the enum's title", 4 | "description": "This is \nthe enum's description.", 5 | "oneOf": [ 6 | { 7 | "type": "string", 8 | "enum": [ 9 | "UndocumentedUnit", 10 | "UndocumentedUnit2" 11 | ] 12 | }, 13 | { 14 | "description": "This comment is included in the generated schema :)", 15 | "type": "string", 16 | "const": "DocumentedUnit" 17 | }, 18 | { 19 | "title": "Complex variant", 20 | "description": "This is a struct-like variant.", 21 | "type": "object", 22 | "properties": { 23 | "Complex": { 24 | "type": "object", 25 | "properties": { 26 | "my_nullable_string": { 27 | "title": "A nullable string", 28 | "description": "This field is a nullable string.\n\nThis\nis\n the second\n line!\n\n\n\n\nAnd this is the third!", 29 | "type": [ 30 | "string", 31 | "null" 32 | ] 33 | } 34 | }, 35 | "required": [ 36 | "my_nullable_string" 37 | ] 38 | } 39 | }, 40 | "required": [ 41 | "Complex" 42 | ], 43 | "additionalProperties": false 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/docs.rs~doc_comments_override.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "OverrideDocs struct", 4 | "description": "New description", 5 | "type": "object", 6 | "properties": { 7 | "my_int": { 8 | "title": "My integer", 9 | "description": "This is an i32", 10 | "type": "integer", 11 | "format": "int32" 12 | }, 13 | "my_undocumented_bool": { 14 | "type": "boolean" 15 | }, 16 | "my_documented_bool": { 17 | "title": "Documented bool", 18 | "description": "CAPITALIZED", 19 | "type": "boolean" 20 | } 21 | }, 22 | "required": [ 23 | "my_int", 24 | "my_undocumented_bool", 25 | "my_documented_bool" 26 | ] 27 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/docs.rs~doc_comments_struct.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "This is the struct's title", 4 | "description": "This is the struct's description.", 5 | "type": "object", 6 | "properties": { 7 | "my_int": { 8 | "title": "An integer", 9 | "type": "integer", 10 | "format": "int32" 11 | }, 12 | "my_undocumented_bool": { 13 | "type": "boolean" 14 | }, 15 | "my_unit": { 16 | "description": "A unit struct instance", 17 | "$ref": "#/$defs/MyUnitStruct" 18 | }, 19 | "my_documented_bool": { 20 | "title": "Documented bool", 21 | "description": "This bool is documented", 22 | "type": "boolean" 23 | } 24 | }, 25 | "required": [ 26 | "my_int", 27 | "my_undocumented_bool", 28 | "my_unit", 29 | "my_documented_bool" 30 | ], 31 | "$defs": { 32 | "MyUnitStruct": { 33 | "title": "A Unit", 34 | "type": "null" 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/either.rs~either.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Either_int32_or_Either_boolean_or_null", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "Left": { 9 | "type": "integer", 10 | "format": "int32" 11 | } 12 | }, 13 | "additionalProperties": false, 14 | "required": [ 15 | "Left" 16 | ] 17 | }, 18 | { 19 | "type": "object", 20 | "properties": { 21 | "Right": { 22 | "oneOf": [ 23 | { 24 | "type": "object", 25 | "properties": { 26 | "Left": { 27 | "type": "boolean" 28 | } 29 | }, 30 | "additionalProperties": false, 31 | "required": [ 32 | "Left" 33 | ] 34 | }, 35 | { 36 | "type": "object", 37 | "properties": { 38 | "Right": { 39 | "type": "null" 40 | } 41 | }, 42 | "additionalProperties": false, 43 | "required": [ 44 | "Right" 45 | ] 46 | } 47 | ] 48 | } 49 | }, 50 | "additionalProperties": false, 51 | "required": [ 52 | "Right" 53 | ] 54 | } 55 | ] 56 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/enum_repr.rs~enum_repr.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "EnumWithReprAttr", 4 | "description": "Description from comment", 5 | "type": "integer", 6 | "enum": [ 7 | 0, 8 | 1, 9 | 5, 10 | 6, 11 | 3 12 | ] 13 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/enums.rs~no_variants.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "NoVariants", 4 | "not": {} 5 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/enums.rs~renamed.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Renamed", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "struct_variant": { 9 | "type": "object", 10 | "properties": { 11 | "FIELD": { 12 | "type": "string" 13 | } 14 | }, 15 | "required": [ 16 | "FIELD" 17 | ] 18 | } 19 | }, 20 | "required": [ 21 | "struct_variant" 22 | ], 23 | "additionalProperties": false 24 | }, 25 | { 26 | "type": "object", 27 | "properties": { 28 | "custom name variant": { 29 | "type": "object", 30 | "properties": { 31 | "custom name field": { 32 | "type": "string" 33 | } 34 | }, 35 | "required": [ 36 | "custom name field" 37 | ] 38 | } 39 | }, 40 | "required": [ 41 | "custom name variant" 42 | ], 43 | "additionalProperties": false 44 | } 45 | ] 46 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/enums.rs~unit_variants_with_doc_comments.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "SoundOfMusic", 4 | "oneOf": [ 5 | { 6 | "title": "A deer", 7 | "description": "A female deer", 8 | "type": "string", 9 | "const": "Do" 10 | }, 11 | { 12 | "description": "A drop of golden sun", 13 | "type": "string", 14 | "const": "Re" 15 | }, 16 | { 17 | "description": "A name I call myself", 18 | "type": "string", 19 | "const": "Mi" 20 | } 21 | ] 22 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/enums.rs~untagged_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Untagged", 4 | "anyOf": [ 5 | { 6 | "type": "null" 7 | }, 8 | { 9 | "type": "object", 10 | "additionalProperties": { 11 | "type": "string" 12 | } 13 | }, 14 | { 15 | "$ref": "#/$defs/UnitStruct" 16 | }, 17 | { 18 | "$ref": "#/$defs/Struct" 19 | }, 20 | { 21 | "type": "object", 22 | "properties": { 23 | "foo": { 24 | "type": "integer", 25 | "format": "int32" 26 | }, 27 | "bar": { 28 | "type": "boolean" 29 | } 30 | }, 31 | "required": [ 32 | "foo", 33 | "bar" 34 | ] 35 | }, 36 | { 37 | "type": "array", 38 | "prefixItems": [ 39 | { 40 | "type": "integer", 41 | "format": "int32" 42 | }, 43 | { 44 | "type": "boolean" 45 | } 46 | ], 47 | "minItems": 2, 48 | "maxItems": 2 49 | }, 50 | { 51 | "type": "null" 52 | }, 53 | { 54 | "type": "integer", 55 | "format": "uint64", 56 | "minimum": 0 57 | }, 58 | { 59 | "type": "string", 60 | "pattern": "^\\d+ (true|false)$" 61 | } 62 | ], 63 | "$defs": { 64 | "UnitStruct": { 65 | "type": "null" 66 | }, 67 | "Struct": { 68 | "type": "object", 69 | "properties": { 70 | "foo": { 71 | "type": "integer", 72 | "format": "int32" 73 | }, 74 | "bar": { 75 | "type": "boolean" 76 | } 77 | }, 78 | "required": [ 79 | "foo", 80 | "bar" 81 | ] 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/enums_deny_unknown_fields.rs~untagged_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Untagged", 4 | "anyOf": [ 5 | { 6 | "type": "null" 7 | }, 8 | { 9 | "type": "object", 10 | "additionalProperties": { 11 | "type": "string" 12 | } 13 | }, 14 | { 15 | "$ref": "#/$defs/Struct" 16 | }, 17 | { 18 | "$ref": "#/$defs/StructDenyUnknownFields" 19 | }, 20 | { 21 | "type": "object", 22 | "properties": { 23 | "foo": { 24 | "type": "integer", 25 | "format": "int32" 26 | }, 27 | "bar": { 28 | "type": "boolean" 29 | } 30 | }, 31 | "additionalProperties": false, 32 | "required": [ 33 | "foo", 34 | "bar" 35 | ] 36 | } 37 | ], 38 | "$defs": { 39 | "Struct": { 40 | "type": "object", 41 | "properties": { 42 | "foo": { 43 | "type": "integer", 44 | "format": "int32" 45 | }, 46 | "bar": { 47 | "type": "boolean" 48 | } 49 | }, 50 | "required": [ 51 | "foo", 52 | "bar" 53 | ] 54 | }, 55 | "StructDenyUnknownFields": { 56 | "type": "object", 57 | "properties": { 58 | "baz": { 59 | "type": "integer", 60 | "format": "int32" 61 | }, 62 | "foobar": { 63 | "type": "boolean" 64 | } 65 | }, 66 | "additionalProperties": false, 67 | "required": [ 68 | "baz", 69 | "foobar" 70 | ] 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/examples.rs~examples.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Struct", 4 | "type": "object", 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "format": "int32", 9 | "examples": [ 10 | 8, 11 | null 12 | ] 13 | }, 14 | "bar": { 15 | "type": "boolean" 16 | }, 17 | "baz": { 18 | "type": [ 19 | "string", 20 | "null" 21 | ], 22 | "examples": [ 23 | null, 24 | "foo" 25 | ] 26 | } 27 | }, 28 | "required": [ 29 | "foo", 30 | "bar" 31 | ], 32 | "examples": [ 33 | { 34 | "foo": 0, 35 | "bar": false, 36 | "baz": null 37 | }, 38 | null 39 | ] 40 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/examples.rs~examples.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Struct", 4 | "type": "object", 5 | "properties": { 6 | "foo": { 7 | "type": "integer", 8 | "format": "int32", 9 | "examples": [ 10 | 8, 11 | null 12 | ] 13 | }, 14 | "bar": { 15 | "type": "boolean" 16 | }, 17 | "baz": { 18 | "type": [ 19 | "string", 20 | "null" 21 | ], 22 | "examples": [ 23 | null, 24 | "foo" 25 | ] 26 | } 27 | }, 28 | "required": [ 29 | "foo", 30 | "bar", 31 | "baz" 32 | ], 33 | "examples": [ 34 | { 35 | "foo": 0, 36 | "bar": false, 37 | "baz": null 38 | }, 39 | null 40 | ] 41 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/extend.rs~extend_externally_tagged_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "ExternalEnum", 4 | "oneOf": [ 5 | { 6 | "type": "string", 7 | "const": "Unit", 8 | "foo": "bar" 9 | }, 10 | { 11 | "type": "object", 12 | "properties": { 13 | "NewType": true 14 | }, 15 | "required": [ 16 | "NewType" 17 | ], 18 | "additionalProperties": false, 19 | "foo": "bar" 20 | }, 21 | { 22 | "type": "object", 23 | "properties": { 24 | "Tuple": { 25 | "type": "array", 26 | "prefixItems": [ 27 | { 28 | "type": "integer", 29 | "format": "int32" 30 | }, 31 | { 32 | "type": "boolean" 33 | } 34 | ], 35 | "minItems": 2, 36 | "maxItems": 2 37 | } 38 | }, 39 | "required": [ 40 | "Tuple" 41 | ], 42 | "additionalProperties": false, 43 | "foo": "bar" 44 | }, 45 | { 46 | "type": "object", 47 | "properties": { 48 | "Struct": { 49 | "type": "object", 50 | "properties": { 51 | "i": { 52 | "type": "integer", 53 | "format": "int32" 54 | }, 55 | "b": { 56 | "type": "boolean" 57 | } 58 | }, 59 | "required": [ 60 | "i", 61 | "b" 62 | ] 63 | } 64 | }, 65 | "required": [ 66 | "Struct" 67 | ], 68 | "additionalProperties": false, 69 | "foo": "bar" 70 | } 71 | ], 72 | "foo": "bar" 73 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/extend.rs~extend_internally_tagged_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "InternalEnum", 4 | "oneOf": [ 5 | { 6 | "type": "object", 7 | "properties": { 8 | "t": { 9 | "type": "string", 10 | "const": "Unit" 11 | } 12 | }, 13 | "required": [ 14 | "t" 15 | ], 16 | "foo": "bar" 17 | }, 18 | { 19 | "type": "object", 20 | "properties": { 21 | "t": { 22 | "type": "string", 23 | "const": "NewType" 24 | } 25 | }, 26 | "required": [ 27 | "t" 28 | ], 29 | "foo": "bar" 30 | }, 31 | { 32 | "type": "object", 33 | "properties": { 34 | "i": { 35 | "type": "integer", 36 | "format": "int32" 37 | }, 38 | "b": { 39 | "type": "boolean" 40 | }, 41 | "t": { 42 | "type": "string", 43 | "const": "Struct" 44 | } 45 | }, 46 | "required": [ 47 | "t", 48 | "i", 49 | "b" 50 | ], 51 | "foo": "bar" 52 | } 53 | ], 54 | "foo": "bar" 55 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/extend.rs~extend_struct.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Struct", 4 | "type": "object", 5 | "properties": { 6 | "value": { 7 | "foo": "bar" 8 | }, 9 | "int": { 10 | "type": [ 11 | "number", 12 | "string" 13 | ], 14 | "format": "int32" 15 | } 16 | }, 17 | "required": [ 18 | "value", 19 | "int" 20 | ], 21 | "obj": { 22 | "array": [ 23 | null, 24 | null 25 | ] 26 | }, 27 | "3": 3.0, 28 | "pi": 3.14 29 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/extend.rs~extend_tuple_struct.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TupleStruct", 4 | "type": "array", 5 | "prefixItems": [ 6 | { 7 | "foo": "bar" 8 | }, 9 | { 10 | "type": [ 11 | "number", 12 | "string" 13 | ], 14 | "format": "uint", 15 | "minimum": 0 16 | } 17 | ], 18 | "minItems": 2, 19 | "maxItems": 2, 20 | "obj": { 21 | "array": [ 22 | null, 23 | null 24 | ] 25 | }, 26 | "3": 3.0, 27 | "pi": 3.14 28 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/extend.rs~extend_untagged_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "UntaggedEnum", 4 | "anyOf": [ 5 | { 6 | "type": "null", 7 | "foo": "bar" 8 | }, 9 | { 10 | "foo": "bar" 11 | }, 12 | { 13 | "type": "array", 14 | "prefixItems": [ 15 | { 16 | "type": "integer", 17 | "format": "int32" 18 | }, 19 | { 20 | "type": "boolean" 21 | } 22 | ], 23 | "minItems": 2, 24 | "maxItems": 2, 25 | "foo": "bar" 26 | }, 27 | { 28 | "type": "object", 29 | "properties": { 30 | "i": { 31 | "type": "integer", 32 | "format": "int32" 33 | }, 34 | "b": { 35 | "type": "boolean" 36 | } 37 | }, 38 | "required": [ 39 | "i", 40 | "b" 41 | ], 42 | "foo": "bar" 43 | } 44 | ], 45 | "foo": "bar" 46 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/flatten.rs~flattened_struct.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Flat", 4 | "type": "object", 5 | "properties": { 6 | "f": { 7 | "type": "number", 8 | "format": "float" 9 | }, 10 | "b": { 11 | "type": "boolean" 12 | }, 13 | "s": { 14 | "type": "string" 15 | }, 16 | "v": { 17 | "type": "array", 18 | "items": { 19 | "type": "integer", 20 | "format": "int32" 21 | } 22 | } 23 | }, 24 | "required": [ 25 | "f", 26 | "b", 27 | "v" 28 | ] 29 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/flatten.rs~flattened_value.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "FlattenValue", 4 | "type": "object", 5 | "properties": { 6 | "flag": { 7 | "type": "boolean" 8 | } 9 | }, 10 | "required": [ 11 | "flag" 12 | ], 13 | "additionalProperties": true 14 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/from_value.rs~custom_struct_openapi3.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://spec.openapis.org/oas/3.0/schema/2024-10-18#/definitions/Schema", 3 | "title": "MyStruct", 4 | "type": "object", 5 | "properties": { 6 | "myInt": { 7 | "type": "integer" 8 | }, 9 | "myBool": { 10 | "type": "boolean" 11 | }, 12 | "myNullableEnum": {}, 13 | "myInnerStruct": { 14 | "type": "object", 15 | "properties": { 16 | "my_map": { 17 | "type": "object", 18 | "additionalProperties": { 19 | "type": "number" 20 | } 21 | }, 22 | "my_vec": { 23 | "type": "array", 24 | "items": { 25 | "type": "number" 26 | } 27 | }, 28 | "my_empty_map": { 29 | "type": "object", 30 | "additionalProperties": true 31 | }, 32 | "my_empty_vec": { 33 | "type": "array", 34 | "items": {} 35 | }, 36 | "my_tuple": { 37 | "type": "array", 38 | "minItems": 2, 39 | "maxItems": 2, 40 | "items": [ 41 | { 42 | "type": "string", 43 | "minLength": 1, 44 | "maxLength": 1 45 | }, 46 | { 47 | "type": "integer" 48 | } 49 | ] 50 | } 51 | } 52 | } 53 | }, 54 | "example": { 55 | "myInt": 123, 56 | "myBool": true, 57 | "myNullableEnum": null, 58 | "myInnerStruct": { 59 | "my_map": { 60 | "k": 1.23 61 | }, 62 | "my_vec": [ 63 | 1.0, 64 | 2.0, 65 | 3.0 66 | ], 67 | "my_empty_map": {}, 68 | "my_empty_vec": [], 69 | "my_tuple": [ 70 | "💩", 71 | 42 72 | ] 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/from_value.rs~json_value.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "type": "object", 4 | "properties": { 5 | "zero": { 6 | "type": "integer" 7 | }, 8 | "zeroPointZero": { 9 | "type": "number" 10 | }, 11 | "bool": { 12 | "type": "boolean" 13 | }, 14 | "null": true, 15 | "object": { 16 | "type": "object", 17 | "properties": { 18 | "strings": { 19 | "type": "array", 20 | "items": { 21 | "type": "string" 22 | } 23 | }, 24 | "mixed": { 25 | "type": "array", 26 | "items": true 27 | } 28 | } 29 | } 30 | }, 31 | "examples": [ 32 | { 33 | "zero": 0, 34 | "zeroPointZero": 0.0, 35 | "bool": true, 36 | "null": null, 37 | "object": { 38 | "strings": [ 39 | "foo", 40 | "bar" 41 | ], 42 | "mixed": [ 43 | 1, 44 | true 45 | ] 46 | } 47 | } 48 | ] 49 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/garde.rs~garde_attrs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "GardeAttrStruct", 4 | "type": "object", 5 | "properties": { 6 | "min_max": { 7 | "type": "number", 8 | "format": "float", 9 | "minimum": 1.0, 10 | "maximum": 100.0 11 | }, 12 | "min_max2": { 13 | "type": "number", 14 | "format": "float", 15 | "minimum": 1.0, 16 | "maximum": 10.0 17 | }, 18 | "regex_str": { 19 | "type": "string", 20 | "pattern": "^[Hh]ello" 21 | }, 22 | "contains_str": { 23 | "type": "string", 24 | "pattern": "substring\\.\\.\\." 25 | }, 26 | "email_address": { 27 | "type": "string", 28 | "format": "email" 29 | }, 30 | "homepage": { 31 | "type": "string", 32 | "format": "uri" 33 | }, 34 | "non_empty_str": { 35 | "type": "string", 36 | "minLength": 1, 37 | "maxLength": 10 38 | }, 39 | "pair": { 40 | "type": "array", 41 | "items": { 42 | "type": "string", 43 | "minLength": 1 44 | }, 45 | "minItems": 2, 46 | "maxItems": 2 47 | }, 48 | "required_option": { 49 | "type": "boolean" 50 | }, 51 | "x": { 52 | "type": "integer", 53 | "format": "int32", 54 | "minimum": -100, 55 | "maximum": 100 56 | } 57 | }, 58 | "required": [ 59 | "min_max", 60 | "min_max2", 61 | "regex_str", 62 | "contains_str", 63 | "email_address", 64 | "homepage", 65 | "non_empty_str", 66 | "pair", 67 | "required_option", 68 | "x" 69 | ] 70 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/garde.rs~garde_attrs_newtype.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "GardeAttrNewType", 4 | "type": "integer", 5 | "format": "uint8", 6 | "minimum": 0, 7 | "maximum": 10 8 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/garde.rs~garde_attrs_tuple.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "GardeAttrTuple", 4 | "type": "array", 5 | "prefixItems": [ 6 | { 7 | "type": "integer", 8 | "format": "uint8", 9 | "minimum": 0, 10 | "maximum": 10 11 | }, 12 | { 13 | "type": "boolean" 14 | } 15 | ], 16 | "minItems": 2, 17 | "maxItems": 2 18 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/inline_subschemas.rs~struct_normal.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "MyJob", 4 | "type": "object", 5 | "properties": { 6 | "spec": { 7 | "type": "object", 8 | "properties": { 9 | "replicas": { 10 | "type": "integer", 11 | "format": "uint32", 12 | "minimum": 0 13 | } 14 | }, 15 | "required": [ 16 | "replicas" 17 | ] 18 | } 19 | }, 20 | "required": [ 21 | "spec" 22 | ] 23 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/inline_subschemas.rs~struct_recursive.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "RecursiveOuter", 4 | "type": "object", 5 | "properties": { 6 | "direct": { 7 | "anyOf": [ 8 | { 9 | "$ref": "#" 10 | }, 11 | { 12 | "type": "null" 13 | } 14 | ] 15 | }, 16 | "indirect": { 17 | "type": [ 18 | "object", 19 | "null" 20 | ], 21 | "properties": { 22 | "recursive": { 23 | "$ref": "#" 24 | } 25 | }, 26 | "required": [ 27 | "recursive" 28 | ] 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/inline_subschemas.rs~struct_recursive.ser.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "RecursiveOuter", 4 | "type": "object", 5 | "properties": { 6 | "direct": { 7 | "anyOf": [ 8 | { 9 | "$ref": "#" 10 | }, 11 | { 12 | "type": "null" 13 | } 14 | ] 15 | }, 16 | "indirect": { 17 | "type": [ 18 | "object", 19 | "null" 20 | ], 21 | "properties": { 22 | "recursive": { 23 | "$ref": "#" 24 | } 25 | }, 26 | "required": [ 27 | "recursive" 28 | ] 29 | } 30 | }, 31 | "required": [ 32 | "direct", 33 | "indirect" 34 | ] 35 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/jiff.rs~jiff.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "JiffTypes", 4 | "type": "object", 5 | "properties": { 6 | "date_time_ts": { 7 | "type": "string", 8 | "format": "date-time" 9 | }, 10 | "date_time_zoned": { 11 | "type": "string", 12 | "format": "zoned-date-time" 13 | }, 14 | "naive_date": { 15 | "type": "string", 16 | "format": "date" 17 | }, 18 | "naive_date_time": { 19 | "type": "string", 20 | "format": "partial-date-time" 21 | }, 22 | "naive_time": { 23 | "type": "string", 24 | "format": "partial-time" 25 | }, 26 | "duration": { 27 | "type": "string", 28 | "format": "duration" 29 | }, 30 | "span": { 31 | "type": "string", 32 | "format": "duration" 33 | } 34 | }, 35 | "required": [ 36 | "date_time_ts", 37 | "date_time_zoned", 38 | "naive_date", 39 | "naive_date_time", 40 | "naive_time", 41 | "duration", 42 | "span" 43 | ] 44 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/map.rs~maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Maps", 4 | "type": "object", 5 | "properties": { 6 | "s_map": { 7 | "type": "object", 8 | "additionalProperties": { 9 | "type": "boolean" 10 | } 11 | }, 12 | "i_map": { 13 | "type": "object", 14 | "patternProperties": { 15 | "^-?\\d+$": { 16 | "type": "boolean" 17 | } 18 | }, 19 | "additionalProperties": false 20 | }, 21 | "u_map": { 22 | "type": "object", 23 | "patternProperties": { 24 | "^\\d+$": { 25 | "type": "boolean" 26 | } 27 | }, 28 | "additionalProperties": false 29 | }, 30 | "pattern_map": { 31 | "type": "object", 32 | "patternProperties": { 33 | "^[0-9a-f]*$": { 34 | "type": "boolean" 35 | } 36 | }, 37 | "additionalProperties": false 38 | } 39 | }, 40 | "required": [ 41 | "s_map", 42 | "i_map", 43 | "u_map", 44 | "pattern_map" 45 | ] 46 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/remote_derive.rs~lifetime_param.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "LifetimeParam", 4 | "type": "object", 5 | "properties": { 6 | "s": { 7 | "$ref": "#/$defs/Str" 8 | } 9 | }, 10 | "required": [ 11 | "s" 12 | ], 13 | "$defs": { 14 | "Str": { 15 | "type": "string" 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/remote_derive.rs~simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Process", 4 | "type": "object", 5 | "properties": { 6 | "wall_time": { 7 | "$ref": "#/$defs/Duration" 8 | } 9 | }, 10 | "required": [ 11 | "wall_time" 12 | ], 13 | "$defs": { 14 | "Duration": { 15 | "type": "object", 16 | "properties": { 17 | "secs": { 18 | "type": "integer", 19 | "format": "int64" 20 | }, 21 | "nanos": { 22 | "type": "integer", 23 | "format": "int32" 24 | } 25 | }, 26 | "required": [ 27 | "secs", 28 | "nanos" 29 | ] 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/remote_derive.rs~type_param.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TypeParam_for_string", 4 | "type": "object", 5 | "properties": { 6 | "byte_or_bool": { 7 | "$ref": "#/$defs/Or_for_uint8_and_boolean" 8 | }, 9 | "unit_or_t": { 10 | "$ref": "#/$defs/Or_for_null_and_string" 11 | } 12 | }, 13 | "required": [ 14 | "byte_or_bool", 15 | "unit_or_t" 16 | ], 17 | "$defs": { 18 | "Or_for_uint8_and_boolean": { 19 | "anyOf": [ 20 | { 21 | "type": "integer", 22 | "format": "uint8", 23 | "minimum": 0, 24 | "maximum": 255 25 | }, 26 | { 27 | "type": "boolean" 28 | } 29 | ] 30 | }, 31 | "Or_for_null_and_string": { 32 | "anyOf": [ 33 | { 34 | "type": "null" 35 | }, 36 | { 37 | "type": "string" 38 | } 39 | ] 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/same_name.rs~same_name.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Config2", 4 | "type": "object", 5 | "properties": { 6 | "a_cfg": { 7 | "$ref": "#/$defs/Config" 8 | }, 9 | "b_cfg": { 10 | "$ref": "#/$defs/Config2" 11 | }, 12 | "c_cfg": { 13 | "$ref": "#/$defs/Config3" 14 | } 15 | }, 16 | "required": [ 17 | "a_cfg", 18 | "b_cfg", 19 | "c_cfg" 20 | ], 21 | "$defs": { 22 | "Config": { 23 | "type": "object", 24 | "properties": { 25 | "test": { 26 | "type": "string" 27 | } 28 | }, 29 | "required": [ 30 | "test" 31 | ] 32 | }, 33 | "Config2": { 34 | "type": "object", 35 | "properties": { 36 | "test2": { 37 | "type": "string" 38 | } 39 | }, 40 | "required": [ 41 | "test2" 42 | ] 43 | }, 44 | "Config3": { 45 | "type": "object", 46 | "properties": { 47 | "test3": { 48 | "type": "string" 49 | } 50 | }, 51 | "required": [ 52 | "test3" 53 | ] 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/schema_with.rs~schema_with.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Struct", 4 | "type": "object", 5 | "properties": { 6 | "x": { 7 | "type": "string", 8 | "pattern": "^-?\\d+$" 9 | } 10 | }, 11 | "required": [ 12 | "x" 13 | ] 14 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/semver.rs~semver.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "SemVer", 4 | "type": "string", 5 | "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" 6 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/skip.rs~skip_enum_variants.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Enum", 4 | "type": "string", 5 | "enum": [ 6 | "Included1", 7 | "Included2" 8 | ] 9 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/skip.rs~skip_struct_field.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Struct", 4 | "type": "object", 5 | "properties": { 6 | "included": { 7 | "type": "boolean" 8 | } 9 | }, 10 | "additionalProperties": false, 11 | "required": [ 12 | "included" 13 | ] 14 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/structs.rs~deny_unknown_fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "DenyUnknownFields", 4 | "type": "object", 5 | "properties": { 6 | "foo": { 7 | "type": "string" 8 | }, 9 | "bar": { 10 | "type": "boolean" 11 | } 12 | }, 13 | "additionalProperties": false, 14 | "required": [ 15 | "foo", 16 | "bar" 17 | ] 18 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/structs.rs~newtype.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "NewType", 4 | "type": "string" 5 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/structs.rs~normal.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "NormalStruct", 4 | "type": "object", 5 | "properties": { 6 | "foo": { 7 | "type": "string" 8 | }, 9 | "bar": { 10 | "type": "boolean" 11 | } 12 | }, 13 | "required": [ 14 | "foo", 15 | "bar" 16 | ] 17 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/structs.rs~renamed_fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "RenamedFields", 4 | "type": "object", 5 | "properties": { 6 | "camelCase": { 7 | "type": "integer", 8 | "format": "int32" 9 | }, 10 | "new_name": { 11 | "type": "integer", 12 | "format": "int32" 13 | } 14 | }, 15 | "required": [ 16 | "camelCase", 17 | "new_name" 18 | ] 19 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/structs.rs~tuple.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TupleStruct", 4 | "type": "array", 5 | "prefixItems": [ 6 | { 7 | "type": "string" 8 | }, 9 | { 10 | "type": "boolean" 11 | } 12 | ], 13 | "minItems": 2, 14 | "maxItems": 2 15 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/structs.rs~unit.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "UnitStruct", 4 | "type": "null" 5 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/transform.rs~transform_enum.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "External", 4 | "oneOf": [ 5 | { 6 | "type": "string", 7 | "const": "Unit", 8 | "x-propertyCount": 0, 9 | "x-upperType": "STRING" 10 | }, 11 | { 12 | "type": "object", 13 | "properties": { 14 | "NewType": true 15 | }, 16 | "required": [ 17 | "NewType" 18 | ], 19 | "additionalProperties": false, 20 | "x-propertyCount": 1, 21 | "x-upperType": "OBJECT" 22 | } 23 | ], 24 | "x-propertyCount": 0 25 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/transform.rs~transform_struct.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Struct", 4 | "type": "object", 5 | "properties": { 6 | "value": true, 7 | "int": { 8 | "type": "integer", 9 | "format": "int32", 10 | "x-propertyCount": 0, 11 | "x-upperType": "INTEGER" 12 | } 13 | }, 14 | "required": [ 15 | "value", 16 | "int" 17 | ], 18 | "x-upperType": "OBJECT", 19 | "x-propertyCount": 2 20 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/transparent.rs~transparent_newtype_with_validation.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TransparentNewTypeWithValidation", 4 | "type": "string", 5 | "minLength": 1 6 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/transparent.rs~transparent_struct_with_doc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "TransparentStructWithDoc", 4 | "description": "A doc comment", 5 | "type": "string" 6 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/url.rs~url.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "Url", 4 | "type": "string", 5 | "format": "uri" 6 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/uuid.rs~uuid.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2019-09/schema", 3 | "title": "Uuid", 4 | "type": "string", 5 | "format": "uuid" 6 | } -------------------------------------------------------------------------------- /schemars/tests/integration/snapshots/schemars/tests/integration/validator.rs~validate_attrs.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft/2020-12/schema", 3 | "title": "ValidateAttrStruct", 4 | "type": "object", 5 | "properties": { 6 | "min_max": { 7 | "type": "number", 8 | "format": "float", 9 | "minimum": 1.0, 10 | "maximum": 100.0 11 | }, 12 | "min_max2": { 13 | "type": "number", 14 | "format": "float", 15 | "minimum": 1.0, 16 | "maximum": 10.0 17 | }, 18 | "regex_str": { 19 | "type": "string", 20 | "pattern": "^[Hh]ello" 21 | }, 22 | "contains_str": { 23 | "type": "string", 24 | "pattern": "substring\\.\\.\\." 25 | }, 26 | "email_address": { 27 | "type": "string", 28 | "format": "email" 29 | }, 30 | "homepage": { 31 | "type": "string", 32 | "format": "uri" 33 | }, 34 | "non_empty_str": { 35 | "type": "string", 36 | "minLength": 1, 37 | "maxLength": 100 38 | }, 39 | "pair": { 40 | "type": "array", 41 | "items": { 42 | "type": "string" 43 | }, 44 | "minItems": 2, 45 | "maxItems": 2 46 | }, 47 | "required_option": { 48 | "type": "boolean" 49 | }, 50 | "x": { 51 | "type": "integer", 52 | "format": "int32", 53 | "minimum": -100, 54 | "maximum": 100 55 | } 56 | }, 57 | "required": [ 58 | "min_max", 59 | "min_max2", 60 | "regex_str", 61 | "contains_str", 62 | "email_address", 63 | "homepage", 64 | "non_empty_str", 65 | "pair", 66 | "required_option", 67 | "x" 68 | ] 69 | } -------------------------------------------------------------------------------- /schemars/tests/integration/transparent.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | 3 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 4 | #[serde(transparent)] 5 | pub struct TransparentStruct { 6 | inner: String, 7 | } 8 | 9 | #[test] 10 | fn transparent_struct() { 11 | test!(TransparentStruct) 12 | .assert_identical::() 13 | .assert_allows_ser_roundtrip_default() 14 | .assert_matches_de_roundtrip(arbitrary_values()); 15 | } 16 | 17 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 18 | #[serde(transparent)] 19 | /// A doc comment 20 | pub struct TransparentStructWithDoc { 21 | inner: String, 22 | } 23 | 24 | #[test] 25 | fn transparent_struct_with_doc() { 26 | test!(TransparentStructWithDoc) 27 | .assert_snapshot() 28 | .assert_allows_ser_roundtrip_default() 29 | .assert_matches_de_roundtrip(arbitrary_values()); 30 | } 31 | 32 | #[derive(JsonSchema, Deserialize, Serialize, Default)] 33 | #[serde(transparent)] 34 | pub struct TransparentNewType(String); 35 | 36 | #[test] 37 | fn transparent_newtype() { 38 | test!(TransparentNewType) 39 | .assert_identical::() 40 | .assert_allows_ser_roundtrip_default() 41 | .assert_matches_de_roundtrip(arbitrary_values()); 42 | } 43 | 44 | #[derive(JsonSchema, Deserialize, Serialize)] 45 | #[serde(transparent)] 46 | pub struct TransparentNewTypeWithValidation(#[schemars(length(min = 1))] String); 47 | 48 | #[test] 49 | fn transparent_newtype_with_validation() { 50 | test!(TransparentNewTypeWithValidation) 51 | .with_validator(|v| !v.0.is_empty()) 52 | .assert_snapshot() 53 | .assert_allows_ser_roundtrip([TransparentNewTypeWithValidation("a@a.com".into())]) 54 | .assert_matches_de_roundtrip(arbitrary_values()); 55 | } 56 | -------------------------------------------------------------------------------- /schemars/tests/integration/url.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use url2::Url; 3 | 4 | #[test] 5 | fn url() { 6 | test!(Url) 7 | .assert_snapshot() 8 | .assert_allows_ser_roundtrip( 9 | ["http://example.com", "data:text/plain,test"] 10 | .iter() 11 | .map(|s| s.parse().unwrap()), 12 | ) 13 | .assert_matches_de_roundtrip(arbitrary_values()); 14 | } 15 | -------------------------------------------------------------------------------- /schemars/tests/integration/uuid.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use schemars::generate::SchemaSettings; 3 | use uuid1::Uuid; 4 | 5 | #[test] 6 | fn uuid() { 7 | // Must run with draft 2019-09 due to https://github.com/Stranger6667/jsonschema-rs/issues/456 8 | test!(Uuid, SchemaSettings::draft2019_09()) 9 | .assert_snapshot() 10 | .assert_allows_ser_roundtrip([Uuid::nil(), Uuid::max(), Uuid::from_u128(1234567890)]) 11 | .assert_matches_de_roundtrip(arbitrary_values()); 12 | } 13 | -------------------------------------------------------------------------------- /schemars/tests/ui.rs: -------------------------------------------------------------------------------- 1 | #[test] 2 | fn ui() { 3 | let t = trybuild::TestCases::new(); 4 | t.compile_fail("tests/ui/*.rs"); 5 | } 6 | -------------------------------------------------------------------------------- /schemars/tests/ui/example_fn.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema; 2 | 3 | #[derive(JsonSchema)] 4 | #[schemars(example = "my_fn")] 5 | pub struct Struct; 6 | 7 | fn my_fn() {} 8 | 9 | fn main() {} 10 | -------------------------------------------------------------------------------- /schemars/tests/ui/example_fn.stderr: -------------------------------------------------------------------------------- 1 | error: `example` value must be an expression, and string literals that may be interpreted as function paths are currently disallowed to avoid migration errors (this restriction may be relaxed in a future version of schemars). 2 | If you want to use the result of a function, use `#[schemars(example = my_fn())]`. 3 | Or to use the string literal value, use `#[schemars(example = &"my_fn")]`. 4 | --> tests/ui/example_fn.rs:4:22 5 | | 6 | 4 | #[schemars(example = "my_fn")] 7 | | ^^^^^^^ 8 | -------------------------------------------------------------------------------- /schemars/tests/ui/invalid_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema; 2 | 3 | #[derive(JsonSchema)] 4 | #[serde( 5 | default = 0, 6 | foo, 7 | deny_unknown_fields, 8 | deny_unknown_fields, 9 | inline = 1, 10 | inline, 11 | inline, 12 | with = "String", 13 | serialize_with = "String" 14 | )] 15 | pub struct Struct1 { 16 | #[serde(serialize_with = "u64")] 17 | pub field: u32, 18 | } 19 | 20 | #[derive(JsonSchema)] 21 | #[schemars( 22 | default = 0, 23 | foo, 24 | deny_unknown_fields, 25 | deny_unknown_fields, 26 | inline = 1, 27 | inline, 28 | inline, 29 | with = "String", 30 | serialize_with = "String" 31 | )] 32 | pub struct Struct2 { 33 | #[schemars(serialize_with = "u64")] 34 | pub field: u32, 35 | } 36 | 37 | fn main() {} 38 | -------------------------------------------------------------------------------- /schemars/tests/ui/invalid_extend.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema; 2 | 3 | #[derive(JsonSchema)] 4 | #[schemars(extend(x))] 5 | #[schemars(extend("x"))] 6 | #[schemars(extend("x" = ))] 7 | #[schemars(extend("y" = "ok!", "y" = "duplicated!"), extend("y" = "duplicated!"))] 8 | #[schemars(extend("y" = "duplicated!"))] 9 | pub struct Struct; 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /schemars/tests/ui/invalid_extend.stderr: -------------------------------------------------------------------------------- 1 | error: expected string literal 2 | --> tests/ui/invalid_extend.rs:4:19 3 | | 4 | 4 | #[schemars(extend(x))] 5 | | ^ 6 | 7 | error: expected `=` 8 | --> tests/ui/invalid_extend.rs:5:22 9 | | 10 | 5 | #[schemars(extend("x"))] 11 | | ^ 12 | 13 | error: Expected extension value 14 | --> tests/ui/invalid_extend.rs:6:25 15 | | 16 | 6 | #[schemars(extend("x" = ))] 17 | | ^ 18 | 19 | error: Duplicate extension key 'y' 20 | --> tests/ui/invalid_extend.rs:7:32 21 | | 22 | 7 | #[schemars(extend("y" = "ok!", "y" = "duplicated!"), extend("y" = "duplicated!"))] 23 | | ^^^ 24 | 25 | error: Duplicate extension key 'y' 26 | --> tests/ui/invalid_extend.rs:7:61 27 | | 28 | 7 | #[schemars(extend("y" = "ok!", "y" = "duplicated!"), extend("y" = "duplicated!"))] 29 | | ^^^ 30 | 31 | error: Duplicate extension key 'y' 32 | --> tests/ui/invalid_extend.rs:8:19 33 | | 34 | 8 | #[schemars(extend("y" = "duplicated!"))] 35 | | ^^^ 36 | -------------------------------------------------------------------------------- /schemars/tests/ui/invalid_validation_attrs.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema; 2 | 3 | #[derive(JsonSchema)] 4 | #[validate(email)] 5 | pub struct Struct1(#[validate(regex, foo, length(min = 1, equal = 2, bar))] String); 6 | 7 | #[derive(JsonSchema)] 8 | #[schemars(email)] 9 | pub struct Struct2(#[schemars(regex, foo, length(min = 1, equal = 2, bar))] String); 10 | 11 | #[derive(JsonSchema)] 12 | pub struct Struct3( 13 | #[validate( 14 | regex = "foo", 15 | contains = "bar", 16 | regex(pattern = "baz"), 17 | regex(path = "baz"), 18 | phone, 19 | email, 20 | url 21 | )] 22 | String, 23 | ); 24 | 25 | #[derive(JsonSchema)] 26 | pub struct Struct4( 27 | #[schemars( 28 | regex = "foo", 29 | contains = "bar", 30 | regex(path = "baz"), 31 | regex(pattern = "baz"), 32 | phone, 33 | email(code = "code_str", message = "message"), 34 | email = "foo", 35 | email, 36 | email, 37 | url 38 | )] 39 | String, 40 | ); 41 | 42 | fn main() {} 43 | -------------------------------------------------------------------------------- /schemars/tests/ui/repr_missing.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema_repr; 2 | 3 | #[derive(JsonSchema_repr)] 4 | pub enum Enum { 5 | Unit, 6 | } 7 | 8 | fn main() {} 9 | -------------------------------------------------------------------------------- /schemars/tests/ui/repr_missing.stderr: -------------------------------------------------------------------------------- 1 | error: JsonSchema_repr: missing #[repr(...)] attribute 2 | --> $DIR/repr_missing.rs:3:10 3 | | 4 | 3 | #[derive(JsonSchema_repr)] 5 | | ^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `JsonSchema_repr` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /schemars/tests/ui/repr_non_unit_variant.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema_repr; 2 | 3 | #[derive(JsonSchema_repr)] 4 | #[repr(u8)] 5 | pub enum Enum { 6 | Unit, 7 | EmptyTuple(), 8 | } 9 | 10 | fn main() {} 11 | -------------------------------------------------------------------------------- /schemars/tests/ui/repr_non_unit_variant.stderr: -------------------------------------------------------------------------------- 1 | error: JsonSchema_repr: must be a unit variant 2 | --> $DIR/repr_non_unit_variant.rs:7:5 3 | | 4 | 7 | EmptyTuple(), 5 | | ^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /schemars/tests/ui/schema_for_arg_value.rs: -------------------------------------------------------------------------------- 1 | use schemars::schema_for; 2 | 3 | fn main() { 4 | let _schema = schema_for!(123); 5 | } 6 | -------------------------------------------------------------------------------- /schemars/tests/ui/schema_for_arg_value.stderr: -------------------------------------------------------------------------------- 1 | error: This argument to `schema_for!` is not a type - did you mean to use `schema_for_value!` instead? 2 | --> $DIR/schema_for_arg_value.rs:4:19 3 | | 4 | 4 | let _schema = schema_for!(123); 5 | | ^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the macro `schema_for` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /schemars/tests/ui/transform_str.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema; 2 | 3 | #[derive(JsonSchema)] 4 | #[schemars(transform = "x")] 5 | pub struct Struct; 6 | 7 | fn main() {} 8 | -------------------------------------------------------------------------------- /schemars/tests/ui/transform_str.stderr: -------------------------------------------------------------------------------- 1 | error: Expected a `fn(&mut Schema)` or other value implementing `schemars::transform::Transform`, found `&str`. 2 | Did you mean `#[schemars(transform = x)]`? 3 | --> tests/ui/transform_str.rs:4:24 4 | | 5 | 4 | #[schemars(transform = "x")] 6 | | ^^^ 7 | -------------------------------------------------------------------------------- /schemars_derive/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /schemars_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "schemars_derive" 3 | description = "Macros for #[derive(JsonSchema)], for use with schemars" 4 | homepage = "https://graham.cool/schemars/" 5 | repository = "https://github.com/GREsau/schemars" 6 | version = "1.0.0-alpha.20" 7 | authors = ["Graham Esau "] 8 | edition = "2021" 9 | license = "MIT" 10 | readme = "README.md" 11 | keywords = ["rust", "json-schema", "serde"] 12 | categories = ["encoding", "no-std"] 13 | rust-version = "1.74" 14 | 15 | [lib] 16 | proc-macro = true 17 | 18 | [dependencies] 19 | proc-macro2 = "1.0" 20 | quote = "1.0" 21 | syn = "2.0" 22 | serde_derive_internals = "0.29" 23 | 24 | [dev-dependencies] 25 | syn = { version = "2.0", features = ["extra-traits"] } 26 | pretty_assertions = "1.2.1" 27 | -------------------------------------------------------------------------------- /schemars_derive/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /schemars_derive/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /schemars_derive/attributes.md: -------------------------------------------------------------------------------- 1 | ../docs/_includes/attributes.md -------------------------------------------------------------------------------- /schemars_derive/deriving.md: -------------------------------------------------------------------------------- 1 | ../docs/_includes/deriving.md -------------------------------------------------------------------------------- /schemars_derive/docs-rs-custom.css: -------------------------------------------------------------------------------- 1 | ../docs-rs-custom.css -------------------------------------------------------------------------------- /schemars_derive/src/attr/doc.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::ToTokens; 3 | use syn::{Attribute, Expr, ExprLit, Lit}; 4 | 5 | pub fn get_doc(attrs: &[Attribute]) -> Option { 6 | let mut macro_args: TokenStream = TokenStream::new(); 7 | 8 | for (i, line) in attrs 9 | .iter() 10 | .filter(|a| a.path().is_ident("doc")) 11 | .flat_map(|a| a.meta.require_name_value()) 12 | .enumerate() 13 | { 14 | if i > 0 { 15 | macro_args.extend([quote!(, "\n",)]); 16 | } 17 | 18 | if let Expr::Lit(ExprLit { 19 | lit: Lit::Str(lit_str), 20 | .. 21 | }) = &line.value 22 | { 23 | if let Some(trimmed) = lit_str.value().strip_prefix(' ') { 24 | trimmed.to_tokens(&mut macro_args); 25 | continue; 26 | } 27 | } 28 | 29 | line.value.to_tokens(&mut macro_args); 30 | } 31 | 32 | if macro_args.is_empty() { 33 | None 34 | } else { 35 | Some(parse_quote!(::core::concat!(#macro_args))) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /schemars_derive/src/idents.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::{Ident, Span, TokenStream, TokenTree}; 2 | use quote::TokenStreamExt; 3 | 4 | pub const GENERATOR: ConstIdent = ConstIdent("generator"); 5 | pub const SCHEMA: ConstIdent = ConstIdent("schema"); 6 | pub const STRUCT_DEFAULT: ConstIdent = ConstIdent("struct_default"); 7 | 8 | pub struct ConstIdent(&'static str); 9 | 10 | impl quote::ToTokens for ConstIdent { 11 | fn to_tokens(&self, tokens: &mut TokenStream) { 12 | let ident = Ident::new(self.0, Span::call_site()); 13 | tokens.append(TokenTree::from(ident)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /update-examples.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | cd schemars/examples 5 | 6 | rm -f *.schema.json 7 | 8 | for file in *.rs 9 | do 10 | example=${file%.rs} 11 | cargo run --example "$example" > "$example.schema.json" 12 | done 13 | 14 | cd ../.. 15 | 16 | rm -f docs/_includes/examples/*.rs 17 | rm -f docs/_includes/examples/*.schema.json 18 | 19 | cp schemars/examples/* docs/_includes/examples/ 20 | -------------------------------------------------------------------------------- /update-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | cd schemars 5 | 6 | rm -f tests/actual/*.json 7 | 8 | TRYBUILD=overwrite SNAPSHOTS=overwrite cargo test --all-features --no-fail-fast --tests || : 9 | 10 | if ls tests/actual/*.json 1> /dev/null 2>&1; then 11 | mv -f tests/actual/*.json tests/expected/ 12 | else 13 | echo "Test schemas are up-to-date." 14 | fi 15 | --------------------------------------------------------------------------------