Compare commits
10 commits
0a7aa5ebf0
...
f8c1fe21b7
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f8c1fe21b7 | ||
![]() |
13ffa14d1f | ||
![]() |
ae4fe29592 | ||
![]() |
b54680e7dc | ||
![]() |
95023c2ab0 | ||
![]() |
e5168819a4 | ||
![]() |
a479e6cc0e | ||
![]() |
092dc17ae4 | ||
![]() |
65346d6683 | ||
![]() |
6a03758284 |
254 changed files with 5998 additions and 4959 deletions
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
|
@ -8,12 +8,12 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
rust:
|
rust:
|
||||||
- 1.65.0
|
- 1.70.0
|
||||||
- stable
|
- stable
|
||||||
- beta
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
include:
|
include:
|
||||||
- rust: 1.65.0
|
- rust: 1.70.0
|
||||||
allow_failure: false
|
allow_failure: false
|
||||||
- rust: stable
|
- rust: stable
|
||||||
allow_failure: false
|
allow_failure: false
|
||||||
|
@ -23,12 +23,10 @@ jobs:
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v4
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: dtolnay/rust-toolchain@master
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
|
||||||
toolchain: ${{ matrix.rust }}
|
toolchain: ${{ matrix.rust }}
|
||||||
override: true
|
|
||||||
- name: Check with no feature flags
|
- name: Check with no feature flags
|
||||||
run: cargo check --verbose --no-default-features
|
run: cargo check --verbose --no-default-features
|
||||||
continue-on-error: ${{ matrix.allow_failure }}
|
continue-on-error: ${{ matrix.allow_failure }}
|
||||||
|
|
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -1,5 +1,27 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [1.0.0-alpha.17] - 2024-12-02
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- For newtype variants of internally-tagged enums, prefer referencing the inner type's schema via `$ref` instead of always inlining the schema (https://github.com/GREsau/schemars/pull/355) _(this change was included in the release notes for 1.0.0-alpha.16, but was accidentally excluded from the published crate)_
|
||||||
|
|
||||||
|
## [1.0.0-alpha.16] - 2024-11-25
|
||||||
|
|
||||||
|
### Removed (_⚠️ breaking changes ⚠️_)
|
||||||
|
|
||||||
|
- the `enumset1`/`enumset` optional dependency has been removed, as its `JsonSchema` impl did not actually match the default serialization format of `EnumSet` (https://github.com/GREsau/schemars/pull/339)
|
||||||
|
|
||||||
|
### Changed (_⚠️ breaking changes ⚠️_)
|
||||||
|
|
||||||
|
- MSRV is now 1.70
|
||||||
|
- [The `example` attribute](https://graham.cool/schemars/deriving/attributes/#example) value is now an arbitrary expression, rather than a string literal identifying a function to call. To avoid silent behaviour changes, the expression must not be a string literal where the value can be parsed as a function path - e.g. `#[schemars(example = "foo")]` is now a compile error, but `#[schemars(example = foo())]` is allowed (as is `#[schemars(example = &"foo")]` if you want the the literal string value `"foo"` to be the example).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The "deserialize" schema for `bytes::Bytes`/`BytesMut` now allows strings, matching the actual deserialize behaviour of the types.
|
||||||
|
- The schema for `either::Either` now matches the actual serialize/deserialize behaviour of that type.
|
||||||
|
|
||||||
## [1.0.0-alpha.15] - 2024-09-05
|
## [1.0.0-alpha.15] - 2024-09-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
1136
Cargo.lock
generated
1136
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,7 @@
|
||||||
[](https://github.com/GREsau/schemars/actions)
|
[](https://github.com/GREsau/schemars/actions)
|
||||||
[](https://crates.io/crates/schemars)
|
[](https://crates.io/crates/schemars)
|
||||||
[](https://docs.rs/schemars/1.0.0--latest)
|
[](https://docs.rs/schemars/1.0.0--latest)
|
||||||
[](https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html)
|
[](https://blog.rust-lang.org/2023/06/01/Rust-1.70.0.html)
|
||||||
|
|
||||||
Generate JSON Schema documents from Rust code
|
Generate JSON Schema documents from Rust code
|
||||||
|
|
||||||
|
@ -268,7 +268,6 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
|
||||||
- `bytes1` - [bytes](https://crates.io/crates/bytes) (^1.0)
|
- `bytes1` - [bytes](https://crates.io/crates/bytes) (^1.0)
|
||||||
- `chrono04` - [chrono](https://crates.io/crates/chrono) (^0.4)
|
- `chrono04` - [chrono](https://crates.io/crates/chrono) (^0.4)
|
||||||
- `either1` - [either](https://crates.io/crates/either) (^1.3)
|
- `either1` - [either](https://crates.io/crates/either) (^1.3)
|
||||||
- `enumset1` - [enumset](https://crates.io/crates/enumset) (^1.0)
|
|
||||||
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
|
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
|
||||||
- `rust_decimal1` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
|
- `rust_decimal1` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
|
||||||
- `semver1` - [semver](https://crates.io/crates/semver) (^1.0.9)
|
- `semver1` - [semver](https://crates.io/crates/semver) (^1.0.9)
|
||||||
|
@ -281,5 +280,5 @@ For example, to implement `JsonSchema` on types from `chrono`, enable it as a fe
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
schemars = { version = "1.0.0-alpha.15", features = ["chrono04"] }
|
schemars = { version = "1.0.0-alpha.17", features = ["chrono04"] }
|
||||||
```
|
```
|
||||||
|
|
|
@ -23,10 +23,9 @@ All optional dependencies are now suffixed by their version:
|
||||||
- `url` is now `url2`
|
- `url` is now `url2`
|
||||||
- `bytes` is now `bytes1`
|
- `bytes` is now `bytes1`
|
||||||
- `rust_decimal` is now `rust_decimal1`
|
- `rust_decimal` is now `rust_decimal1`
|
||||||
- `enumset` is now `enumset1`
|
|
||||||
- `smol_str` is now `smol_str02`
|
- `smol_str` is now `smol_str02`
|
||||||
- `semver` is now `semver1`
|
- `semver` is now `semver1`
|
||||||
- `indexmap`, `uuid08`, `arrayvec05` and `bigdecimal03` have been removed
|
- `enumset`, `indexmap`, `uuid08`, `arrayvec05` and `bigdecimal03` have been removed
|
||||||
- `indexmap2`, `arrayvec07` and `bigdecimal04` are unchanged
|
- `indexmap2`, `arrayvec07` and `bigdecimal04` are unchanged
|
||||||
|
|
||||||
## `Schema` is now a wrapper around `serde_json::Value`
|
## `Schema` is now a wrapper around `serde_json::Value`
|
||||||
|
|
|
@ -18,7 +18,6 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
|
||||||
- `bytes1` - [bytes](https://crates.io/crates/bytes) (^1.0)
|
- `bytes1` - [bytes](https://crates.io/crates/bytes) (^1.0)
|
||||||
- `chrono04` - [chrono](https://crates.io/crates/chrono) (^0.4)
|
- `chrono04` - [chrono](https://crates.io/crates/chrono) (^0.4)
|
||||||
- `either1` - [either](https://crates.io/crates/either) (^1.3)
|
- `either1` - [either](https://crates.io/crates/either) (^1.3)
|
||||||
- `enumset1` - [enumset](https://crates.io/crates/enumset) (^1.0)
|
|
||||||
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
|
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
|
||||||
- `rust_decimal1` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
|
- `rust_decimal1` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
|
||||||
- `semver1` - [semver](https://crates.io/crates/semver) (^1.0.9)
|
- `semver1` - [semver](https://crates.io/crates/semver) (^1.0.9)
|
||||||
|
@ -31,5 +30,5 @@ For example, to implement `JsonSchema` on types from `chrono`, enable it as a fe
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
schemars = { version = "1.0.0-alpha.15", features = ["chrono04"] }
|
schemars = { version = "1.0.0-alpha.17", features = ["chrono04"] }
|
||||||
```
|
```
|
||||||
|
|
|
@ -298,13 +298,15 @@ Set on a container, variant or field to set the generated schema's `title` and/o
|
||||||
|
|
||||||
<h3 id="example">
|
<h3 id="example">
|
||||||
|
|
||||||
`#[schemars(example = "some::function")]`
|
`#[schemars(example = value)]`
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
Set on a container, variant or field to include the result of the given function in the generated schema's `examples`. The function should take no parameters and can return any type that implements serde's `Serialize` trait - it does not need to return the same type as the attached struct/field. This attribute can be repeated to specify multiple examples.
|
Set on a container, variant or field to include the given value in the generated schema's `examples`. The value can be any type that implements serde's `Serialize` trait - it does not need to be the same type as the attached struct/field. This attribute can be repeated to specify multiple examples.
|
||||||
|
|
||||||
To use the result of arbitrary expressions as examples, you can instead use the [`extend`](#extend) attribute, e.g. `[schemars(extend("examples" = ["example string"]))]`.
|
In previous versions of schemars, the value had to be a string literal identifying a defined function that would be called to return the actual example value (similar to the [`default`](#default) attribute). To avoid the new attribute behaviour from silently breaking old consumers, string literals consisting of a single word (e.g. `#[schemars(example = "my_fn")]`) or a path (e.g. `#[schemars(example = "my_mod::my_fn")]`) are currently disallowed. This restriction may be relaxed in a future version of schemars, but for now if you want to include such a string as the literal example value, this can be done by borrowing the value, e.g. `#[schemars(example = &"my_fn")]`. If you instead want to call a function to get the example value (mirrorring the old behaviour), you must use an explicit function call expression, e.g. `#[schemars(example = my_fn())]`.
|
||||||
|
|
||||||
|
Alternatively, to directly set multiple examples without repeating `example = ...` attribute, you can instead use the [`extend`](#extend) attribute, e.g. `#[schemars(extend("examples" = [1, 2, 3]))]`.
|
||||||
|
|
||||||
<h3 id="deprecated">
|
<h3 id="deprecated">
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,17 @@ name = "schemars"
|
||||||
description = "Generate JSON Schemas from Rust code"
|
description = "Generate JSON Schemas from Rust code"
|
||||||
homepage = "https://graham.cool/schemars/"
|
homepage = "https://graham.cool/schemars/"
|
||||||
repository = "https://github.com/GREsau/schemars"
|
repository = "https://github.com/GREsau/schemars"
|
||||||
version = "1.0.0-alpha.15"
|
version = "1.0.0-alpha.17"
|
||||||
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
keywords = ["rust", "json-schema", "serde"]
|
keywords = ["rust", "json-schema", "serde"]
|
||||||
categories = ["encoding", "no-std"]
|
categories = ["encoding", "no-std"]
|
||||||
rust-version = "1.65"
|
rust-version = "1.70"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
schemars_derive = { version = "=1.0.0-alpha.15", optional = true, path = "../schemars_derive" }
|
schemars_derive = { version = "=1.0.0-alpha.17", optional = true, path = "../schemars_derive" }
|
||||||
serde = { version = "1.0", default-features = false, features = ["alloc"]}
|
serde = { version = "1.0", default-features = false, features = ["alloc"]}
|
||||||
serde_json = { version = "1.0.127", default-features = false, features = ["alloc"] }
|
serde_json = { version = "1.0.127", default-features = false, features = ["alloc"] }
|
||||||
dyn-clone = "1.0"
|
dyn-clone = "1.0"
|
||||||
|
@ -24,10 +24,9 @@ arrayvec07 = { version = "0.7", default-features = false, optional = true, packa
|
||||||
bigdecimal04 = { version = "0.4", default-features = false, optional = true, package = "bigdecimal" }
|
bigdecimal04 = { version = "0.4", default-features = false, optional = true, package = "bigdecimal" }
|
||||||
bytes1 = { version = "1.0", default-features = false, optional = true, package = "bytes" }
|
bytes1 = { version = "1.0", default-features = false, optional = true, package = "bytes" }
|
||||||
chrono04 = { version = "0.4", default-features = false, optional = true, package = "chrono" }
|
chrono04 = { version = "0.4", default-features = false, optional = true, package = "chrono" }
|
||||||
either1 = { version = "1.3", default-features = false, optional = true, package = "either" }
|
either1 = { version = "1.3", default-features = false, optional = true, package = "either" }
|
||||||
enumset1 = { version = "1.0", default-features = false, optional = true, package = "enumset" }
|
|
||||||
indexmap2 = { version = "2.0", default-features = false, optional = true, package = "indexmap" }
|
indexmap2 = { version = "2.0", default-features = false, optional = true, package = "indexmap" }
|
||||||
rust_decimal1 = { version = "1", default-features = false, optional = true, package = "rust_decimal"}
|
rust_decimal1 = { version = "1", default-features = false, optional = true, package = "rust_decimal" }
|
||||||
semver1 = { version = "1.0.9", default-features = false, optional = true, package = "semver" }
|
semver1 = { version = "1.0.9", default-features = false, optional = true, package = "semver" }
|
||||||
smallvec1 = { version = "1.0", default-features = false, optional = true, package = "smallvec" }
|
smallvec1 = { version = "1.0", default-features = false, optional = true, package = "smallvec" }
|
||||||
smol_str02 = { version = "0.2.1", default-features = false, optional = true, package = "smol_str" }
|
smol_str02 = { version = "0.2.1", default-features = false, optional = true, package = "smol_str" }
|
||||||
|
@ -38,6 +37,26 @@ uuid1 = { version = "1.0", default-features = false, optional = true, package =
|
||||||
pretty_assertions = "1.2.1"
|
pretty_assertions = "1.2.1"
|
||||||
trybuild = "1.0"
|
trybuild = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
jsonschema = { version = "0.20", default-features = false }
|
||||||
|
snapbox = { version = "0.6.17", features = ["json"] }
|
||||||
|
serde_repr = "0.1.19"
|
||||||
|
# Use github source until published garde version supports `length(equal = ...)` attr
|
||||||
|
garde = { git = "https://github.com/jprochazk/garde.git", rev = "be00ddddf8de14530ee890ccfdbaf0b13fb32852", features = ["derive", "email", "regex", "url"] }
|
||||||
|
validator = { version = "0.18.1", features = ["derive"] }
|
||||||
|
regex = { version = "1.10.6", default-features = false }
|
||||||
|
|
||||||
|
arrayvec07 = { version = "0.7", default-features = false, features = ["serde"], package = "arrayvec"}
|
||||||
|
bigdecimal04 = { version = "0.4", default-features = false, features = ["serde"], package = "bigdecimal" }
|
||||||
|
bytes1 = { version = "1.0", default-features = false, features = ["serde"], package = "bytes" }
|
||||||
|
chrono04 = { version = "0.4", default-features = false, features = ["serde"], package = "chrono" }
|
||||||
|
either1 = { version = "1.3", default-features = false, features = ["serde"], package = "either" }
|
||||||
|
indexmap2 = { version = "2.0", default-features = false, features = ["serde"], package = "indexmap" }
|
||||||
|
rust_decimal1 = { version = "1", default-features = false, features = ["serde"], package = "rust_decimal" }
|
||||||
|
semver1 = { version = "1.0.9", default-features = false, features = ["serde"], package = "semver" }
|
||||||
|
smallvec1 = { version = "1.0", default-features = false, features = ["serde"], package = "smallvec" }
|
||||||
|
smol_str02 = { version = "0.2.1", default-features = false, features = ["serde"], package = "smol_str" }
|
||||||
|
url2 = { version = "2.0", default-features = false, features = ["serde"], package = "url" }
|
||||||
|
uuid1 = { version = "1.0", default-features = false, features = ["serde"], package = "uuid" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["derive", "std"]
|
default = ["derive", "std"]
|
||||||
|
@ -60,66 +79,10 @@ raw_value = ["serde_json/raw_value"]
|
||||||
# For internal/CI use only
|
# For internal/CI use only
|
||||||
_ui_test = []
|
_ui_test = []
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "std_time"
|
|
||||||
required-features = ["std"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "ffi"
|
|
||||||
required-features = ["std"]
|
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "ui"
|
name = "ui"
|
||||||
required-features = ["_ui_test"]
|
required-features = ["_ui_test"]
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "chrono"
|
|
||||||
required-features = ["chrono04"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "indexmap"
|
|
||||||
required-features = ["indexmap2"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "either"
|
|
||||||
required-features = ["either1"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "uuid"
|
|
||||||
required-features = ["uuid1"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "smallvec"
|
|
||||||
required-features = ["smallvec1"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "bytes"
|
|
||||||
required-features = ["bytes1"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "arrayvec"
|
|
||||||
required-features = ["arrayvec07"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "url"
|
|
||||||
required-features = ["url2"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "enumset"
|
|
||||||
required-features = ["enumset1"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "smol_str"
|
|
||||||
required-features = ["smol_str02"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "semver"
|
|
||||||
required-features = ["semver1"]
|
|
||||||
|
|
||||||
[[test]]
|
|
||||||
name = "decimal"
|
|
||||||
required-features = ["rust_decimal1", "bigdecimal04"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--extend-css", "docs-rs-custom.css"]
|
rustdoc-args = ["--extend-css", "docs-rs-custom.css"]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::_alloc_prelude::*;
|
use crate::_alloc_prelude::*;
|
||||||
use crate::transform::transform_immediate_subschemas;
|
use crate::transform::{transform_immediate_subschemas, Transform};
|
||||||
use crate::{JsonSchema, Schema, SchemaGenerator};
|
use crate::{JsonSchema, Schema, SchemaGenerator};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{json, map::Entry, Map, Value};
|
use serde_json::{json, map::Entry, Map, Value};
|
||||||
|
@ -12,6 +12,39 @@ pub extern crate serde_json;
|
||||||
|
|
||||||
pub use rustdoc::get_title_and_description;
|
pub use rustdoc::get_title_and_description;
|
||||||
|
|
||||||
|
pub fn json_schema_for_internally_tagged_enum_newtype_variant<T: ?Sized + JsonSchema>(
|
||||||
|
generator: &mut SchemaGenerator,
|
||||||
|
) -> Schema {
|
||||||
|
let mut schema = T::json_schema(generator);
|
||||||
|
|
||||||
|
// Inline the newtype's inner schema if any of:
|
||||||
|
// - The type specifies that its schema should always be inlined
|
||||||
|
// - The generator settings specify that all schemas should be inlined
|
||||||
|
// - The inner type is a unit struct, which would cause an unsatisfiable schema due to mismatched `type`.
|
||||||
|
// In this case, we replace its type with "object" in `apply_internal_enum_variant_tag`
|
||||||
|
// - The inner schema specified `"additionalProperties": false` or `"unevaluatedProperties": false`,
|
||||||
|
// since that would disallow the variant tag. If additional/unevaluatedProperties is in the top-level
|
||||||
|
// schema, then we can leave it there, because it will "see" the variant tag property. But if it is
|
||||||
|
// nested e.g. in an `allOf`, then it must be removed, which is why we run `AllowUnknownProperties`
|
||||||
|
// but only on immediate subschemas.
|
||||||
|
|
||||||
|
let mut transform = AllowUnknownProperties::default();
|
||||||
|
transform_immediate_subschemas(&mut transform, &mut schema);
|
||||||
|
|
||||||
|
if T::always_inline_schema()
|
||||||
|
|| generator.settings().inline_subschemas
|
||||||
|
|| schema.get("type").and_then(Value::as_str) == Some("null")
|
||||||
|
|| schema.get("additionalProperties").and_then(Value::as_bool) == Some(false)
|
||||||
|
|| schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false)
|
||||||
|
|| transform.did_modify
|
||||||
|
{
|
||||||
|
return schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...otherwise, we can freely refer to the schema via a `$ref`
|
||||||
|
generator.subschema_for::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
// Helper for generating schemas for flattened `Option` fields.
|
// Helper for generating schemas for flattened `Option` fields.
|
||||||
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
||||||
generator: &mut SchemaGenerator,
|
generator: &mut SchemaGenerator,
|
||||||
|
@ -25,20 +58,29 @@ pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
||||||
|
|
||||||
// Always allow aditional/unevaluated properties, because the outer struct determines
|
// Always allow aditional/unevaluated properties, because the outer struct determines
|
||||||
// whether it denies unknown fields.
|
// whether it denies unknown fields.
|
||||||
allow_unknown_properties(&mut schema);
|
AllowUnknownProperties::default().transform(&mut schema);
|
||||||
|
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allow_unknown_properties(schema: &mut Schema) {
|
#[derive(Default)]
|
||||||
if schema.get("additionalProperties").and_then(Value::as_bool) == Some(false) {
|
struct AllowUnknownProperties {
|
||||||
schema.remove("additionalProperties");
|
did_modify: bool,
|
||||||
}
|
}
|
||||||
if schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false) {
|
|
||||||
schema.remove("unevaluatedProperties");
|
|
||||||
}
|
|
||||||
|
|
||||||
transform_immediate_subschemas(&mut allow_unknown_properties, schema);
|
impl Transform for AllowUnknownProperties {
|
||||||
|
fn transform(&mut self, schema: &mut Schema) {
|
||||||
|
if schema.get("additionalProperties").and_then(Value::as_bool) == Some(false) {
|
||||||
|
schema.remove("additionalProperties");
|
||||||
|
self.did_modify = true;
|
||||||
|
}
|
||||||
|
if schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false) {
|
||||||
|
schema.remove("unevaluatedProperties");
|
||||||
|
self.did_modify = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
transform_immediate_subschemas(self, schema);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hack to simulate specialization:
|
/// Hack to simulate specialization:
|
||||||
|
|
|
@ -671,13 +671,14 @@ where
|
||||||
|
|
||||||
impl Debug for Box<dyn GenTransform> {
|
impl Debug for Box<dyn GenTransform> {
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
#[allow(clippy::used_underscore_items)]
|
||||||
self._debug_type_name(f)
|
self._debug_type_name(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _assert_send() {
|
fn _assert_send() {
|
||||||
fn _assert<T: Send>() {}
|
fn assert<T: Send>() {}
|
||||||
|
|
||||||
_assert::<SchemaSettings>();
|
assert::<SchemaSettings>();
|
||||||
_assert::<SchemaGenerator>();
|
assert::<SchemaGenerator>();
|
||||||
}
|
}
|
||||||
|
|
29
schemars/src/json_schema_impls/bytes1.rs
Normal file
29
schemars/src/json_schema_impls/bytes1.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
use crate::_alloc_prelude::*;
|
||||||
|
use crate::generate::Contract;
|
||||||
|
use crate::{JsonSchema, Schema};
|
||||||
|
use alloc::borrow::Cow;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
impl JsonSchema for bytes1::Bytes {
|
||||||
|
fn schema_name() -> Cow<'static, str> {
|
||||||
|
"Bytes".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema_id() -> Cow<'static, str> {
|
||||||
|
"bytes::Bytes".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(generator: &mut crate::SchemaGenerator) -> crate::Schema {
|
||||||
|
let ty = match generator.contract() {
|
||||||
|
Contract::Deserialize => Value::Array(vec!["array".into(), "string".into()]),
|
||||||
|
Contract::Serialize => "array".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut result = Schema::default();
|
||||||
|
result.insert("type".to_owned(), ty);
|
||||||
|
result.insert("items".to_owned(), generator.subschema_for::<u8>().into());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_impl!(bytes1::BytesMut => bytes1::Bytes);
|
|
@ -58,5 +58,5 @@ macro_rules! formatted_string_impl {
|
||||||
|
|
||||||
formatted_string_impl!(NaiveDate, "date");
|
formatted_string_impl!(NaiveDate, "date");
|
||||||
formatted_string_impl!(NaiveDateTime, "partial-date-time");
|
formatted_string_impl!(NaiveDateTime, "partial-date-time");
|
||||||
formatted_string_impl!(NaiveTime, "partial-date-time");
|
formatted_string_impl!(NaiveTime, "partial-time");
|
||||||
formatted_string_impl!(DateTime, "date-time", <Tz: TimeZone> JsonSchema for DateTime<Tz>);
|
formatted_string_impl!(DateTime, "date-time", <Tz: TimeZone> JsonSchema for DateTime<Tz>);
|
||||||
|
|
|
@ -17,7 +17,28 @@ impl<L: JsonSchema, R: JsonSchema> JsonSchema for Either<L, R> {
|
||||||
|
|
||||||
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
||||||
json_schema!({
|
json_schema!({
|
||||||
"anyOf": [generator.subschema_for::<L>(), generator.subschema_for::<R>()],
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"Left": generator.subschema_for::<L>()
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"Left"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"Right": generator.subschema_for::<R>()
|
||||||
|
},
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"Right"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::SchemaGenerator;
|
||||||
use crate::_alloc_prelude::*;
|
use crate::_alloc_prelude::*;
|
||||||
use crate::{json_schema, JsonSchema, Schema};
|
use crate::{json_schema, JsonSchema, Schema};
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
|
use serde_json::json;
|
||||||
use std::ffi::{CStr, CString, OsStr, OsString};
|
use std::ffi::{CStr, CString, OsStr, OsString};
|
||||||
|
|
||||||
impl JsonSchema for OsString {
|
impl JsonSchema for OsString {
|
||||||
|
@ -37,5 +38,31 @@ impl JsonSchema for OsString {
|
||||||
|
|
||||||
forward_impl!(OsStr => OsString);
|
forward_impl!(OsStr => OsString);
|
||||||
|
|
||||||
forward_impl!(CString => Vec<u8>);
|
impl JsonSchema for CString {
|
||||||
forward_impl!(CStr => Vec<u8>);
|
fn schema_name() -> Cow<'static, str> {
|
||||||
|
"CString".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema_id() -> Cow<'static, str> {
|
||||||
|
"std::ffi::CString".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
||||||
|
let ty = if generator.contract().is_deserialize() {
|
||||||
|
json!(["array", "string"])
|
||||||
|
} else {
|
||||||
|
json!("array")
|
||||||
|
};
|
||||||
|
|
||||||
|
json_schema!({
|
||||||
|
"type": ty,
|
||||||
|
"items": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forward_impl!(CStr => CString);
|
||||||
|
|
|
@ -42,8 +42,7 @@ macro_rules! forward_impl {
|
||||||
mod array;
|
mod array;
|
||||||
mod core;
|
mod core;
|
||||||
mod maps;
|
mod maps;
|
||||||
mod nonzero_signed;
|
mod nonzero;
|
||||||
mod nonzero_unsigned;
|
|
||||||
mod primitives;
|
mod primitives;
|
||||||
mod sequences;
|
mod sequences;
|
||||||
mod serdejson;
|
mod serdejson;
|
||||||
|
@ -61,10 +60,7 @@ mod ffi;
|
||||||
mod arrayvec07;
|
mod arrayvec07;
|
||||||
|
|
||||||
#[cfg(feature = "bytes1")]
|
#[cfg(feature = "bytes1")]
|
||||||
mod bytes1 {
|
mod bytes1;
|
||||||
forward_impl!(bytes1::Bytes => alloc::vec::Vec<u8>);
|
|
||||||
forward_impl!(bytes1::BytesMut => alloc::vec::Vec<u8>);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "chrono04")]
|
#[cfg(feature = "chrono04")]
|
||||||
mod chrono04;
|
mod chrono04;
|
||||||
|
@ -75,9 +71,6 @@ mod decimal;
|
||||||
#[cfg(feature = "either1")]
|
#[cfg(feature = "either1")]
|
||||||
mod either1;
|
mod either1;
|
||||||
|
|
||||||
#[cfg(feature = "enumset1")]
|
|
||||||
forward_impl!((<T: enumset1::EnumSetType + crate::JsonSchema> crate::JsonSchema for enumset1::EnumSet<T>) => alloc::collections::BTreeSet<T>);
|
|
||||||
|
|
||||||
#[cfg(feature = "indexmap2")]
|
#[cfg(feature = "indexmap2")]
|
||||||
mod indexmap2;
|
mod indexmap2;
|
||||||
|
|
||||||
|
|
64
schemars/src/json_schema_impls/nonzero.rs
Normal file
64
schemars/src/json_schema_impls/nonzero.rs
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
use crate::_alloc_prelude::*;
|
||||||
|
use crate::{JsonSchema, Schema, SchemaGenerator};
|
||||||
|
use alloc::borrow::Cow;
|
||||||
|
use core::num::*;
|
||||||
|
|
||||||
|
macro_rules! nonzero_signed_impl {
|
||||||
|
($type:ty => $primitive:ty) => {
|
||||||
|
impl JsonSchema for $type {
|
||||||
|
always_inline!();
|
||||||
|
|
||||||
|
fn schema_name() -> Cow<'static, str> {
|
||||||
|
stringify!($type).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema_id() -> Cow<'static, str> {
|
||||||
|
stringify!(std::num::$type).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
||||||
|
let mut schema = <$primitive>::json_schema(generator);
|
||||||
|
schema.insert("not".to_owned(), serde_json::json!({
|
||||||
|
"const": 0
|
||||||
|
}));
|
||||||
|
schema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
nonzero_signed_impl!(NonZeroI8 => i8);
|
||||||
|
nonzero_signed_impl!(NonZeroI16 => i16);
|
||||||
|
nonzero_signed_impl!(NonZeroI32 => i32);
|
||||||
|
nonzero_signed_impl!(NonZeroI64 => i64);
|
||||||
|
nonzero_signed_impl!(NonZeroI128 => i128);
|
||||||
|
nonzero_signed_impl!(NonZeroIsize => isize);
|
||||||
|
|
||||||
|
macro_rules! nonzero_unsigned_impl {
|
||||||
|
($type:ty => $primitive:ty) => {
|
||||||
|
impl JsonSchema for $type {
|
||||||
|
always_inline!();
|
||||||
|
|
||||||
|
fn schema_name() -> Cow<'static, str> {
|
||||||
|
stringify!($type).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn schema_id() -> Cow<'static, str> {
|
||||||
|
stringify!(std::num::$type).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
||||||
|
let mut schema = <$primitive>::json_schema(generator);
|
||||||
|
schema.insert("minimum".to_owned(), 1.into());
|
||||||
|
schema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
nonzero_unsigned_impl!(NonZeroU8 => u8);
|
||||||
|
nonzero_unsigned_impl!(NonZeroU16 => u16);
|
||||||
|
nonzero_unsigned_impl!(NonZeroU32 => u32);
|
||||||
|
nonzero_unsigned_impl!(NonZeroU64 => u64);
|
||||||
|
nonzero_unsigned_impl!(NonZeroU128 => u128);
|
||||||
|
nonzero_unsigned_impl!(NonZeroUsize => usize);
|
|
@ -1,37 +0,0 @@
|
||||||
use crate::SchemaGenerator;
|
|
||||||
use crate::_alloc_prelude::*;
|
|
||||||
use crate::{JsonSchema, Schema};
|
|
||||||
use alloc::borrow::Cow;
|
|
||||||
use core::num::*;
|
|
||||||
|
|
||||||
macro_rules! nonzero_unsigned_impl {
|
|
||||||
($type:ty => $primitive:ty) => {
|
|
||||||
impl JsonSchema for $type {
|
|
||||||
always_inline!();
|
|
||||||
|
|
||||||
fn schema_name() -> Cow<'static, str> {
|
|
||||||
stringify!($type).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn schema_id() -> Cow<'static, str> {
|
|
||||||
stringify!(std::num::$type).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
|
||||||
let mut schema = <$primitive>::json_schema(generator);
|
|
||||||
let object = schema.ensure_object();
|
|
||||||
object.insert("not".to_owned(), serde_json::json!({
|
|
||||||
"const": 0
|
|
||||||
}));
|
|
||||||
schema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
nonzero_unsigned_impl!(NonZeroI8 => i8);
|
|
||||||
nonzero_unsigned_impl!(NonZeroI16 => i16);
|
|
||||||
nonzero_unsigned_impl!(NonZeroI32 => i32);
|
|
||||||
nonzero_unsigned_impl!(NonZeroI64 => i64);
|
|
||||||
nonzero_unsigned_impl!(NonZeroI128 => i128);
|
|
||||||
nonzero_unsigned_impl!(NonZeroIsize => isize);
|
|
|
@ -1,36 +0,0 @@
|
||||||
use crate::JsonSchema;
|
|
||||||
use crate::Schema;
|
|
||||||
use crate::SchemaGenerator;
|
|
||||||
use crate::_alloc_prelude::*;
|
|
||||||
use alloc::borrow::Cow;
|
|
||||||
use core::num::*;
|
|
||||||
|
|
||||||
macro_rules! nonzero_unsigned_impl {
|
|
||||||
($type:ty => $primitive:ty) => {
|
|
||||||
impl JsonSchema for $type {
|
|
||||||
always_inline!();
|
|
||||||
|
|
||||||
fn schema_name() -> Cow<'static, str> {
|
|
||||||
stringify!($type).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn schema_id() -> Cow<'static, str> {
|
|
||||||
stringify!(std::num::$type).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
|
|
||||||
let mut schema = <$primitive>::json_schema(generator);
|
|
||||||
let object = schema.ensure_object();
|
|
||||||
object.insert("minimum".to_owned(), 1.into());
|
|
||||||
schema
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
nonzero_unsigned_impl!(NonZeroU8 => u8);
|
|
||||||
nonzero_unsigned_impl!(NonZeroU16 => u16);
|
|
||||||
nonzero_unsigned_impl!(NonZeroU32 => u32);
|
|
||||||
nonzero_unsigned_impl!(NonZeroU64 => u64);
|
|
||||||
nonzero_unsigned_impl!(NonZeroU128 => u128);
|
|
||||||
nonzero_unsigned_impl!(NonZeroUsize => usize);
|
|
|
@ -4,10 +4,8 @@ use alloc::borrow::Cow;
|
||||||
use semver1::Version;
|
use semver1::Version;
|
||||||
|
|
||||||
impl JsonSchema for Version {
|
impl JsonSchema for Version {
|
||||||
always_inline!();
|
|
||||||
|
|
||||||
fn schema_name() -> Cow<'static, str> {
|
fn schema_name() -> Cow<'static, str> {
|
||||||
"Version".into()
|
"SemVer".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn schema_id() -> Cow<'static, str> {
|
fn schema_id() -> Cow<'static, str> {
|
||||||
|
|
|
@ -145,7 +145,6 @@ pub mod r#gen {
|
||||||
///
|
///
|
||||||
/// assert_eq!(<GenericType<i32>>::schema_id(), <&mut GenericType<&i32>>::schema_id());
|
/// assert_eq!(<GenericType<i32>>::schema_id(), <&mut GenericType<&i32>>::schema_id());
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
pub trait JsonSchema {
|
pub trait JsonSchema {
|
||||||
/// Whether JSON Schemas generated for this type should be included directly in parent schemas,
|
/// Whether JSON Schemas generated for this type should be included directly in parent schemas,
|
||||||
/// rather than being re-used where possible using the `$ref` keyword.
|
/// rather than being re-used where possible using the `$ref` keyword.
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Actual Generated Schemas
|
|
||||||
|
|
||||||
If a test fails because a generated schema did not match the expected JSON, then the actual schema will be written to a JSON file in this directory.
|
|
|
@ -1,12 +0,0 @@
|
||||||
mod util;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn arrayvec07() -> TestResult {
|
|
||||||
test_default_generated_schema::<arrayvec07::ArrayVec<i32, 16>>("arrayvec")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn arrayvec07_string() -> TestResult {
|
|
||||||
test_default_generated_schema::<arrayvec07::ArrayString<16>>("arrayvec_string")
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
mod util;
|
|
||||||
use bytes1::{Bytes, BytesMut};
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bytes() -> TestResult {
|
|
||||||
test_default_generated_schema::<(Bytes, BytesMut)>("bytes")
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
mod util;
|
|
||||||
use chrono04::prelude::*;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct ChronoTypes {
|
|
||||||
weekday: Weekday,
|
|
||||||
date_time: DateTime<Utc>,
|
|
||||||
naive_date: NaiveDate,
|
|
||||||
naive_date_time: NaiveDateTime,
|
|
||||||
naive_time: NaiveTime,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn chrono_types() -> TestResult {
|
|
||||||
test_default_generated_schema::<ChronoTypes>("chrono-types")
|
|
||||||
}
|
|
|
@ -1,214 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::{generate::SchemaSettings, JsonSchema};
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(rename_all(serialize = "SCREAMING-KEBAB-CASE"))]
|
|
||||||
struct MyStruct {
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
read_only: bool,
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
write_only: bool,
|
|
||||||
#[schemars(default)]
|
|
||||||
default: bool,
|
|
||||||
#[schemars(skip_serializing_if = "anything")]
|
|
||||||
skip_serializing_if: bool,
|
|
||||||
#[schemars(rename(serialize = "ser_renamed", deserialize = "de_renamed"))]
|
|
||||||
renamed: bool,
|
|
||||||
option: Option<bool>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_deserialize() -> TestResult {
|
|
||||||
test_generated_schema::<MyStruct>(
|
|
||||||
"contract_deserialize",
|
|
||||||
SchemaSettings::default().for_deserialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_serialize() -> TestResult {
|
|
||||||
test_generated_schema::<MyStruct>(
|
|
||||||
"contract_serialize",
|
|
||||||
SchemaSettings::default().for_serialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct TupleStruct(
|
|
||||||
String,
|
|
||||||
#[schemars(skip_serializing)] bool,
|
|
||||||
String,
|
|
||||||
#[schemars(skip_deserializing)] bool,
|
|
||||||
String,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_deserialize_tuple_struct() -> TestResult {
|
|
||||||
test_generated_schema::<TupleStruct>(
|
|
||||||
"contract_deserialize_tuple_struct",
|
|
||||||
SchemaSettings::default().for_deserialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_serialize_tuple_struct() -> TestResult {
|
|
||||||
test_generated_schema::<TupleStruct>(
|
|
||||||
"contract_serialize_tuple_struct",
|
|
||||||
SchemaSettings::default().for_serialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(
|
|
||||||
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
|
||||||
rename_all_fields(serialize = "PascalCase")
|
|
||||||
)]
|
|
||||||
enum ExternalEnum {
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyUnit,
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyUnit,
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyStruct { s: String },
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyStruct { i: isize },
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
|
||||||
RenamedUnit,
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
|
||||||
RenamedStruct { b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_deserialize_external_tag_enum() -> TestResult {
|
|
||||||
test_generated_schema::<ExternalEnum>(
|
|
||||||
"contract_deserialize_external_tag_enum",
|
|
||||||
SchemaSettings::default().for_deserialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_serialize_external_tag_enum() -> TestResult {
|
|
||||||
test_generated_schema::<ExternalEnum>(
|
|
||||||
"contract_serialize_external_tag_enum",
|
|
||||||
SchemaSettings::default().for_serialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(
|
|
||||||
tag = "tag",
|
|
||||||
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
|
||||||
rename_all_fields(serialize = "PascalCase")
|
|
||||||
)]
|
|
||||||
enum InternalEnum {
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyUnit,
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyUnit,
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyStruct { s: String },
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyStruct { i: isize },
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
|
||||||
RenamedUnit,
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
|
||||||
RenamedStruct { b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_deserialize_internal_tag_enum() -> TestResult {
|
|
||||||
test_generated_schema::<InternalEnum>(
|
|
||||||
"contract_deserialize_internal_tag_enum",
|
|
||||||
SchemaSettings::default().for_deserialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_serialize_internal_tag_enum() -> TestResult {
|
|
||||||
test_generated_schema::<InternalEnum>(
|
|
||||||
"contract_serialize_internal_tag_enum",
|
|
||||||
SchemaSettings::default().for_serialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(
|
|
||||||
tag = "tag",
|
|
||||||
content = "content",
|
|
||||||
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
|
||||||
rename_all_fields(serialize = "PascalCase")
|
|
||||||
)]
|
|
||||||
enum AdjacentEnum {
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyUnit,
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyUnit,
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyStruct { s: String },
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyStruct { i: isize },
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
|
||||||
RenamedUnit,
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
|
||||||
RenamedStruct { b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_deserialize_adjacent_tag_enum() -> TestResult {
|
|
||||||
test_generated_schema::<AdjacentEnum>(
|
|
||||||
"contract_deserialize_adjacent_tag_enum",
|
|
||||||
SchemaSettings::default().for_deserialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_serialize_adjacent_tag_enum() -> TestResult {
|
|
||||||
test_generated_schema::<AdjacentEnum>(
|
|
||||||
"contract_serialize_adjacent_tag_enum",
|
|
||||||
SchemaSettings::default().for_serialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(
|
|
||||||
untagged,
|
|
||||||
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
|
||||||
rename_all_fields(serialize = "PascalCase")
|
|
||||||
)]
|
|
||||||
enum UntaggedEnum {
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyUnit,
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyUnit,
|
|
||||||
#[schemars(skip_deserializing)]
|
|
||||||
ReadOnlyStruct { s: String },
|
|
||||||
#[schemars(skip_serializing)]
|
|
||||||
WriteOnlyStruct { i: isize },
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
|
||||||
RenamedUnit,
|
|
||||||
#[schemars(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
|
||||||
RenamedStruct { b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_deserialize_untagged_enum() -> TestResult {
|
|
||||||
test_generated_schema::<UntaggedEnum>(
|
|
||||||
"contract_deserialize_untagged_enum",
|
|
||||||
SchemaSettings::default().for_deserialize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn contract_serialize_untagged_enum() -> TestResult {
|
|
||||||
test_generated_schema::<UntaggedEnum>(
|
|
||||||
"contract_serialize_untagged_enum",
|
|
||||||
SchemaSettings::default().for_serialize(),
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
mod util;
|
|
||||||
use ::schemars as not_schemars;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
use std as schemars;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(not_schemars::JsonSchema)]
|
|
||||||
#[schemars(crate = "not_schemars")]
|
|
||||||
struct Struct {
|
|
||||||
/// This is a document
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_crate_alias() -> TestResult {
|
|
||||||
test_default_generated_schema::<Struct>("crate_alias")
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
mod util;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rust_decimal() -> TestResult {
|
|
||||||
test_default_generated_schema::<rust_decimal1::Decimal>("rust_decimal")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bigdecimal04() -> TestResult {
|
|
||||||
test_default_generated_schema::<bigdecimal04::BigDecimal>("bigdecimal04")
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
fn is_default<T: Default + PartialEq>(value: &T) -> bool {
|
|
||||||
value == &T::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ten_and_true() -> MyStruct2 {
|
|
||||||
MyStruct2 {
|
|
||||||
my_int: 10,
|
|
||||||
my_bool: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn six() -> i32 {
|
|
||||||
6
|
|
||||||
}
|
|
||||||
|
|
||||||
fn custom_serialize<S>(value: &MyStruct2, ser: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
ser.collect_str(&format_args!("i:{} b:{}", value.my_int, value.my_bool))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Default, JsonSchema)]
|
|
||||||
#[serde(default)]
|
|
||||||
struct MyStruct {
|
|
||||||
my_int: i32,
|
|
||||||
my_bool: bool,
|
|
||||||
my_optional_string: Option<String>,
|
|
||||||
#[serde(serialize_with = "custom_serialize")]
|
|
||||||
my_struct2: MyStruct2,
|
|
||||||
#[serde(
|
|
||||||
serialize_with = "custom_serialize",
|
|
||||||
skip_serializing_if = "is_default"
|
|
||||||
)]
|
|
||||||
my_struct2_default_skipped: MyStruct2,
|
|
||||||
not_serialize: NotSerialize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Default, JsonSchema, PartialEq)]
|
|
||||||
#[serde(default = "ten_and_true")]
|
|
||||||
struct MyStruct2 {
|
|
||||||
#[serde(default = "six")]
|
|
||||||
my_int: i32,
|
|
||||||
my_bool: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, JsonSchema)]
|
|
||||||
struct NotSerialize;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn schema_default_values() -> TestResult {
|
|
||||||
test_default_generated_schema::<MyStruct>("default")
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
#![allow(deprecated)]
|
|
||||||
|
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[deprecated]
|
|
||||||
struct DeprecatedStruct {
|
|
||||||
foo: i32,
|
|
||||||
#[deprecated]
|
|
||||||
deprecated_field: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deprecated_struct() -> TestResult {
|
|
||||||
test_default_generated_schema::<DeprecatedStruct>("deprecated-struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[deprecated]
|
|
||||||
enum DeprecatedEnum {
|
|
||||||
Unit,
|
|
||||||
#[deprecated]
|
|
||||||
DeprecatedUnitVariant,
|
|
||||||
#[deprecated]
|
|
||||||
DeprecatedStructVariant {
|
|
||||||
foo: i32,
|
|
||||||
#[deprecated]
|
|
||||||
deprecated_field: bool,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn deprecated_enum() -> TestResult {
|
|
||||||
test_default_generated_schema::<DeprecatedEnum>("deprecated-enum")
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
mod util;
|
|
||||||
use either1::Either;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn either() -> TestResult {
|
|
||||||
test_default_generated_schema::<Either<i32, Either<bool, ()>>>("either")
|
|
||||||
}
|
|
|
@ -1,185 +0,0 @@
|
||||||
mod util;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
// Ensure that schemars_derive uses the full path to std::string::String
|
|
||||||
pub struct String;
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct UnitStruct;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(rename_all = "camelCase")]
|
|
||||||
enum External {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
UnitTwo,
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_external_tag() -> TestResult {
|
|
||||||
test_default_generated_schema::<External>("enum-external")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "typeProperty")]
|
|
||||||
enum Internal {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
UnitTwo,
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_internal_tag() -> TestResult {
|
|
||||||
test_default_generated_schema::<Internal>("enum-internal")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(untagged)]
|
|
||||||
enum Untagged {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_untagged() -> TestResult {
|
|
||||||
test_default_generated_schema::<Untagged>("enum-untagged")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "t", content = "c")]
|
|
||||||
enum Adjacent {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
Tuple(i32, bool),
|
|
||||||
UnitTwo,
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_adjacent_tagged() -> TestResult {
|
|
||||||
test_default_generated_schema::<Adjacent>("enum-adjacent-tagged")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "typeProperty")]
|
|
||||||
enum SimpleInternal {
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_simple_internal_tag() -> TestResult {
|
|
||||||
test_default_generated_schema::<SimpleInternal>("enum-simple-internal")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum SoundOfMusic {
|
|
||||||
/// # A deer
|
|
||||||
///
|
|
||||||
/// A female deer
|
|
||||||
Do,
|
|
||||||
/// A drop of golden sun
|
|
||||||
Re,
|
|
||||||
/// A name I call myself
|
|
||||||
Mi,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_unit_with_doc_comments() -> TestResult {
|
|
||||||
test_default_generated_schema::<SoundOfMusic>("enum-unit-doc")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum NoVariants {}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_no_variants() -> TestResult {
|
|
||||||
test_default_generated_schema::<NoVariants>("no-variants")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[serde(rename_all_fields = "PascalCase")]
|
|
||||||
pub enum RenameAllFields {
|
|
||||||
First {
|
|
||||||
nested_attribute: std::string::String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum RenameAll {
|
|
||||||
First { nested_attribute: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub enum RenameAttribute {
|
|
||||||
First {
|
|
||||||
#[serde(rename = "RenamedAttribute")]
|
|
||||||
nested_attribute: std::string::String,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_unit_rename_attribute() -> TestResult {
|
|
||||||
test_default_generated_schema::<RenameAttribute>("enum-rename-attr")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_unit_rename_all_fields() -> TestResult {
|
|
||||||
test_default_generated_schema::<RenameAllFields>("enum-rename-all-fields")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_unit_rename_all() -> TestResult {
|
|
||||||
test_default_generated_schema::<RenameAll>("enum-rename-all")
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
mod util;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
// Ensure that schemars_derive uses the full path to std::string::String
|
|
||||||
pub struct String;
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct UnitStruct;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outer container should always have additionalProperties: false
|
|
||||||
// `Struct` variant should have additionalProperties: false
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
|
|
||||||
enum External {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
UnitTwo,
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_external_tag() -> TestResult {
|
|
||||||
test_default_generated_schema::<External>("enum-external-duf")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only `Struct` variant should have additionalProperties: false
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "typeProperty", deny_unknown_fields)]
|
|
||||||
enum Internal {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
UnitTwo,
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_internal_tag() -> TestResult {
|
|
||||||
test_default_generated_schema::<Internal>("enum-internal-duf")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only `Struct` variant should have additionalProperties: false
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(untagged, deny_unknown_fields)]
|
|
||||||
enum Untagged {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_untagged() -> TestResult {
|
|
||||||
test_default_generated_schema::<Untagged>("enum-untagged-duf")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Outer container and `Struct` variant should have additionalProperties: false
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "t", content = "c", deny_unknown_fields)]
|
|
||||||
enum Adjacent {
|
|
||||||
UnitOne,
|
|
||||||
StringMap(BTreeMap<&'static str, &'static str>),
|
|
||||||
UnitStructNewType(UnitStruct),
|
|
||||||
StructNewType(Struct),
|
|
||||||
Struct {
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
},
|
|
||||||
Tuple(i32, bool),
|
|
||||||
UnitTwo,
|
|
||||||
#[schemars(with = "i32")]
|
|
||||||
WithInt,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_adjacent_tagged() -> TestResult {
|
|
||||||
test_default_generated_schema::<Adjacent>("enum-adjacent-tagged-duf")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "typeProperty", deny_unknown_fields)]
|
|
||||||
enum SimpleInternal {
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_simple_internal_tag() -> TestResult {
|
|
||||||
test_default_generated_schema::<SimpleInternal>("enum-simple-internal-duf")
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::{generate::SchemaSettings, JsonSchema};
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Flat {
|
|
||||||
f: f32,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e1: Enum1,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e2: Enum2,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e3: Enum3,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e4: Enum4,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e5: Enum5,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum Enum1 {
|
|
||||||
B(bool),
|
|
||||||
S(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum Enum2 {
|
|
||||||
U(u32),
|
|
||||||
F(f64),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum Enum3 {
|
|
||||||
B2(bool),
|
|
||||||
S2(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum Enum4 {
|
|
||||||
U2(u32),
|
|
||||||
F2(f64),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
enum Enum5 {
|
|
||||||
B3(bool),
|
|
||||||
S3(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flat_schema() -> TestResult {
|
|
||||||
test_default_generated_schema::<Flat>("enum_flatten")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(deny_unknown_fields)]
|
|
||||||
struct FlatDenyUnknownFields {
|
|
||||||
f: f32,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e1: Enum1,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e2: Enum2,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e3: Enum3,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e4: Enum4,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
e5: Enum5,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flat_schema_duf() -> TestResult {
|
|
||||||
test_default_generated_schema::<FlatDenyUnknownFields>("enum_flatten_duf")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flat_schema_duf_draft07() -> TestResult {
|
|
||||||
test_generated_schema::<FlatDenyUnknownFields>(
|
|
||||||
"enum_flatten_duf_draft07",
|
|
||||||
SchemaSettings::draft07(),
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema_repr;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[derive(JsonSchema_repr)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum Enum {
|
|
||||||
Zero,
|
|
||||||
One,
|
|
||||||
Five = 5,
|
|
||||||
Six,
|
|
||||||
Three = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_repr() -> TestResult {
|
|
||||||
test_default_generated_schema::<Enum>("enum-repr")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema_repr)]
|
|
||||||
#[repr(i64)]
|
|
||||||
#[serde(rename = "Renamed")]
|
|
||||||
/// Description from comment
|
|
||||||
pub enum EnumWithAttrs {
|
|
||||||
Zero,
|
|
||||||
One,
|
|
||||||
Five = 5,
|
|
||||||
Six,
|
|
||||||
Three = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enum_repr_with_attrs() -> TestResult {
|
|
||||||
test_default_generated_schema::<EnumWithAttrs>("enum-repr-with-attrs")
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
mod util;
|
|
||||||
use enumset1::{EnumSet, EnumSetType};
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
// needed to derive EnumSetType when using a crate alias
|
|
||||||
extern crate enumset1 as enumset;
|
|
||||||
|
|
||||||
#[derive(EnumSetType, JsonSchema)]
|
|
||||||
enum Foo {
|
|
||||||
Bar,
|
|
||||||
Baz,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn enumset() -> TestResult {
|
|
||||||
test_default_generated_schema::<EnumSet<Foo>>("enumset")
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Serialize;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[derive(Default, JsonSchema, Serialize)]
|
|
||||||
#[schemars(example = "Struct::default", example = "null")]
|
|
||||||
struct Struct {
|
|
||||||
#[schemars(example = "eight", example = "null")]
|
|
||||||
foo: i32,
|
|
||||||
bar: bool,
|
|
||||||
#[schemars(example = "null")]
|
|
||||||
baz: Option<&'static str>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eight() -> i32 {
|
|
||||||
8
|
|
||||||
}
|
|
||||||
|
|
||||||
fn null() {}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn examples() -> TestResult {
|
|
||||||
test_default_generated_schema::<Struct>("examples")
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "string",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Tuple_of_Array_of_uint8_and_Array_of_uint8",
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint8",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint8",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"my_int": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32",
|
|
||||||
"default": 0
|
|
||||||
},
|
|
||||||
"my_bool": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"my_optional_string": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
],
|
|
||||||
"default": null
|
|
||||||
},
|
|
||||||
"my_struct2": {
|
|
||||||
"$ref": "#/$defs/MyStruct2",
|
|
||||||
"default": "i:0 b:false"
|
|
||||||
},
|
|
||||||
"my_struct2_default_skipped": {
|
|
||||||
"$ref": "#/$defs/MyStruct2"
|
|
||||||
},
|
|
||||||
"not_serialize": {
|
|
||||||
"$ref": "#/$defs/NotSerialize"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$defs": {
|
|
||||||
"MyStruct2": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"my_int": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32",
|
|
||||||
"default": 6
|
|
||||||
},
|
|
||||||
"my_bool": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"NotSerialize": {
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"duration": {
|
|
||||||
"$ref": "#/$defs/Duration"
|
|
||||||
},
|
|
||||||
"time": {
|
|
||||||
"$ref": "#/$defs/SystemTime"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"duration",
|
|
||||||
"time"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"Duration": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secs": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint64",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"nanos": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secs",
|
|
||||||
"nanos"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"SystemTime": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"secs_since_epoch": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint64",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"nanos_since_epoch": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"secs_since_epoch",
|
|
||||||
"nanos_since_epoch"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Either_int32_or_Either_boolean_or_null",
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "RenameAllFields",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"First": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"NestedAttribute": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"NestedAttribute"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"First"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "RenameAll",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"first": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"nested_attribute": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"nested_attribute"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"first"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "RenameAttribute",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"First": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"RenamedAttribute": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"RenamedAttribute"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"First"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "SimpleInternal",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "A"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "B"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "C"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "SimpleInternal",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "A"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "B"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "C"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Set_of_Foo",
|
|
||||||
"type": "array",
|
|
||||||
"uniqueItems": true,
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/$defs/Foo"
|
|
||||||
},
|
|
||||||
"$defs": {
|
|
||||||
"Foo": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Bar",
|
|
||||||
"Baz"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2019-09/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"myInt": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"myBool": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"myNullableEnum": true,
|
|
||||||
"myInnerStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"my_map": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": {
|
|
||||||
"type": "number"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"my_vec": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"my_empty_map": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": true
|
|
||||||
},
|
|
||||||
"my_empty_vec": {
|
|
||||||
"type": "array",
|
|
||||||
"items": true
|
|
||||||
},
|
|
||||||
"my_tuple": {
|
|
||||||
"type": "array",
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2,
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"examples": [
|
|
||||||
{
|
|
||||||
"myInt": 123,
|
|
||||||
"myBool": true,
|
|
||||||
"myNullableEnum": null,
|
|
||||||
"myInnerStruct": {
|
|
||||||
"my_map": {
|
|
||||||
"": 0.0
|
|
||||||
},
|
|
||||||
"my_vec": [
|
|
||||||
"hello",
|
|
||||||
"world"
|
|
||||||
],
|
|
||||||
"my_empty_map": {},
|
|
||||||
"my_empty_vec": [],
|
|
||||||
"my_tuple": [
|
|
||||||
"💩",
|
|
||||||
42
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "IndexMapTypes",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"map": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"set": {
|
|
||||||
"type": "array",
|
|
||||||
"uniqueItems": true,
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"map",
|
|
||||||
"set"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "OuterEnum",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"InnerStruct": {
|
|
||||||
"$ref": "#/$defs/InnerStruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"InnerStruct"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"InnerStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"x": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"x"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "A",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"x": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint8",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"v": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"x",
|
|
||||||
"v"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"my_int": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"my_bool": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"my_nullable_enum": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/MyEnum"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"my_int",
|
|
||||||
"my_bool"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"MyEnum": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"StringNewType": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"StringNewType"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"StructVariant": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"floats": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"floats"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"StructVariant"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"unsigned": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"nonzero_unsigned": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint32",
|
|
||||||
"minimum": 1
|
|
||||||
},
|
|
||||||
"signed": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"nonzero_signed": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32",
|
|
||||||
"not": {
|
|
||||||
"const": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"unsigned",
|
|
||||||
"nonzero_unsigned",
|
|
||||||
"signed",
|
|
||||||
"nonzero_signed"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "OsStrings",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"owned": {
|
|
||||||
"$ref": "#/$defs/OsString"
|
|
||||||
},
|
|
||||||
"borrowed": {
|
|
||||||
"$ref": "#/$defs/OsString"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"owned",
|
|
||||||
"borrowed"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"OsString": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Unix": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint8",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Unix"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Windows": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint16",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Windows"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"range": {
|
|
||||||
"$ref": "#/$defs/Range_of_uint"
|
|
||||||
},
|
|
||||||
"inclusive": {
|
|
||||||
"$ref": "#/$defs/Range_of_double"
|
|
||||||
},
|
|
||||||
"bound": {
|
|
||||||
"$ref": "#/$defs/Bound_of_string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"range",
|
|
||||||
"inclusive",
|
|
||||||
"bound"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"Range_of_uint": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"start": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"minimum": 0
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint",
|
|
||||||
"minimum": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"start",
|
|
||||||
"end"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Range_of_double": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"start": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
},
|
|
||||||
"end": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "double"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"start",
|
|
||||||
"end"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Bound_of_string": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Included": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Included"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Excluded": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Excluded"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"const": "Unbounded"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,86 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Container",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"result1": {
|
|
||||||
"$ref": "#/$defs/Result_of_MyStruct_or_Array_of_string"
|
|
||||||
},
|
|
||||||
"result2": {
|
|
||||||
"$ref": "#/$defs/Result_of_boolean_or_null"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"result1",
|
|
||||||
"result2"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"Result_of_MyStruct_or_Array_of_string": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Ok": {
|
|
||||||
"$ref": "#/$defs/MyStruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Ok"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Err": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Err"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"MyStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"Result_of_boolean_or_null": {
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Ok": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Ok"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Err": {
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Err"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Decimal",
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"number"
|
|
||||||
],
|
|
||||||
"pattern": "^-?[0-9]+(\\.[0-9]+)?([eE][0-9]+)?$"
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "a-new-name-Array_of_string-int32-int32",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"u": {
|
|
||||||
"type": "null"
|
|
||||||
},
|
|
||||||
"v": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"w": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inner": {
|
|
||||||
"$ref": "#/$defs/another-new-name"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"u",
|
|
||||||
"v",
|
|
||||||
"w",
|
|
||||||
"inner"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"another-new-name": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct_for_int32_and_null_and_boolean_and_Array_of_string",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"u": {
|
|
||||||
"type": "null"
|
|
||||||
},
|
|
||||||
"v": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"w": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inner": {
|
|
||||||
"$ref": "#/$defs/MySimpleStruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"u",
|
|
||||||
"v",
|
|
||||||
"w",
|
|
||||||
"inner"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"MySimpleStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MixedGenericStruct_for_MyStruct_for_int32_and_null_and_boolean_and_Array_of_string_and_42_and_z",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"generic": {
|
|
||||||
"$ref": "#/$defs/MyStruct_for_int32_and_null_and_boolean_and_Array_of_string"
|
|
||||||
},
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"generic",
|
|
||||||
"foo"
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"MyStruct_for_int32_and_null_and_boolean_and_Array_of_string": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"u": {
|
|
||||||
"type": "null"
|
|
||||||
},
|
|
||||||
"v": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"w": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inner": {
|
|
||||||
"$ref": "#/$defs/MySimpleStruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"u",
|
|
||||||
"v",
|
|
||||||
"w",
|
|
||||||
"inner"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"MySimpleStruct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Adjacent",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Struct"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "NewType"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Tuple"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Unit"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "External",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"struct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"struct"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"newType": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"newType"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"tuple": {
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"tuple"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"unit": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"unit"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Internal",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Struct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty",
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "NewType"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"typeProperty": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Unit"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"typeProperty"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Untagged",
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Newtype",
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "schema_fn",
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Tuple",
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 3,
|
|
||||||
"maxItems": 3
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "SemverTypes",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"version": {
|
|
||||||
"type": "string",
|
|
||||||
"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-]+)*))?$"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"version"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyEnum",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"Included2"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"Included1": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"Included1"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "MyStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"writable": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float",
|
|
||||||
"writeOnly": true
|
|
||||||
},
|
|
||||||
"included": {
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"writable",
|
|
||||||
"included"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Newtype",
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Struct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"bar": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"baz": {
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo",
|
|
||||||
"bar"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Tuple",
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": [
|
|
||||||
"string",
|
|
||||||
"null"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 3,
|
|
||||||
"maxItems": 3
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Tuple_of_OuterAllowUnknownFields_and_MiddleDenyUnknownFields",
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/OuterAllowUnknownFields"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/MiddleDenyUnknownFields"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2,
|
|
||||||
"$defs": {
|
|
||||||
"OuterAllowUnknownFields": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"outer_field": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"middle_field": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"inner_field": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"outer_field",
|
|
||||||
"middle_field",
|
|
||||||
"inner_field"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"MiddleDenyUnknownFields": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"middle_field": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"inner_field": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"middle_field",
|
|
||||||
"inner_field"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "OuterStruct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"inner": {
|
|
||||||
"anyOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/$defs/InnerStruct"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "null"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"$defs": {
|
|
||||||
"InnerStruct": {
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Struct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"min_max": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float",
|
|
||||||
"minimum": 0.01,
|
|
||||||
"maximum": 100
|
|
||||||
},
|
|
||||||
"min_max2": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 1000
|
|
||||||
},
|
|
||||||
"regex_str1": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[Hh]ello\\b"
|
|
||||||
},
|
|
||||||
"regex_str2": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[Hh]ello\\b"
|
|
||||||
},
|
|
||||||
"contains_str1": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "substring\\.\\.\\."
|
|
||||||
},
|
|
||||||
"contains_str2": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "substring\\.\\.\\."
|
|
||||||
},
|
|
||||||
"email_address": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "email"
|
|
||||||
},
|
|
||||||
"homepage": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri"
|
|
||||||
},
|
|
||||||
"non_empty_str": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 100
|
|
||||||
},
|
|
||||||
"non_empty_str2": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 1000
|
|
||||||
},
|
|
||||||
"pair": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
},
|
|
||||||
"required_option": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"x": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"min_max",
|
|
||||||
"min_max2",
|
|
||||||
"regex_str1",
|
|
||||||
"regex_str2",
|
|
||||||
"contains_str1",
|
|
||||||
"contains_str2",
|
|
||||||
"email_address",
|
|
||||||
"homepage",
|
|
||||||
"non_empty_str",
|
|
||||||
"non_empty_str2",
|
|
||||||
"pair",
|
|
||||||
"required_option",
|
|
||||||
"x"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Struct",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"array_str_length": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 5,
|
|
||||||
"maxLength": 100
|
|
||||||
},
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
},
|
|
||||||
"slice_str_contains": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "substring\\.\\.\\."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vec_str_regex": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[Hh]ello\\b"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vec_str_length": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 100
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vec_str_length2": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 100
|
|
||||||
},
|
|
||||||
"minItems": 1,
|
|
||||||
"maxItems": 3
|
|
||||||
},
|
|
||||||
"vec_str_url": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vec_i32_range": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32",
|
|
||||||
"minimum": -10,
|
|
||||||
"maximum": 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"array_str_length",
|
|
||||||
"slice_str_contains",
|
|
||||||
"vec_str_regex",
|
|
||||||
"vec_str_length",
|
|
||||||
"vec_str_length2",
|
|
||||||
"vec_str_url",
|
|
||||||
"vec_i32_range"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "NewType",
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint8",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 10
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Struct2",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"min_max": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float",
|
|
||||||
"minimum": 0.01,
|
|
||||||
"maximum": 100
|
|
||||||
},
|
|
||||||
"min_max2": {
|
|
||||||
"type": "number",
|
|
||||||
"format": "float",
|
|
||||||
"minimum": 1,
|
|
||||||
"maximum": 1000
|
|
||||||
},
|
|
||||||
"regex_str1": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^[Hh]ello\\b"
|
|
||||||
},
|
|
||||||
"regex_str2": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "^\\d+$"
|
|
||||||
},
|
|
||||||
"contains_str1": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "substring\\.\\.\\."
|
|
||||||
},
|
|
||||||
"contains_str2": {
|
|
||||||
"type": "string",
|
|
||||||
"pattern": "substring\\.\\.\\."
|
|
||||||
},
|
|
||||||
"email_address": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "email"
|
|
||||||
},
|
|
||||||
"homepage": {
|
|
||||||
"type": "string",
|
|
||||||
"format": "uri"
|
|
||||||
},
|
|
||||||
"non_empty_str": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 100
|
|
||||||
},
|
|
||||||
"non_empty_str2": {
|
|
||||||
"type": "string",
|
|
||||||
"minLength": 1,
|
|
||||||
"maxLength": 1000
|
|
||||||
},
|
|
||||||
"pair": {
|
|
||||||
"type": "array",
|
|
||||||
"items": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
},
|
|
||||||
"required_option": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"x": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"min_max",
|
|
||||||
"min_max2",
|
|
||||||
"regex_str1",
|
|
||||||
"regex_str2",
|
|
||||||
"contains_str1",
|
|
||||||
"contains_str2",
|
|
||||||
"email_address",
|
|
||||||
"homepage",
|
|
||||||
"non_empty_str",
|
|
||||||
"non_empty_str2",
|
|
||||||
"pair",
|
|
||||||
"required_option",
|
|
||||||
"x"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Tuple",
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "uint8",
|
|
||||||
"minimum": 0,
|
|
||||||
"maximum": 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde_json::Value;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
const THREE: f64 = 3.0;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(extend("msg" = concat!("hello ", "world"), "obj" = {"array": [null, ()]}))]
|
|
||||||
#[schemars(extend("3" = THREE), extend("pi" = THREE + 0.14))]
|
|
||||||
struct Struct {
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
value: Value,
|
|
||||||
#[schemars(extend("type" = "overridden"))]
|
|
||||||
int: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extend_struct() -> TestResult {
|
|
||||||
test_default_generated_schema::<Struct>("extend_struct")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
enum External {
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Unit,
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
NewType(Value),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Struct { i: i32, b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extend_enum_external() -> TestResult {
|
|
||||||
test_default_generated_schema::<External>("extend_enum_external")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "typeProperty", extend("foo" = "bar"))]
|
|
||||||
enum Internal {
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Unit,
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
NewType(Value),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Struct { i: i32, b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extend_enum_internal() -> TestResult {
|
|
||||||
test_default_generated_schema::<Internal>("extend_enum_internal")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(untagged, extend("foo" = "bar"))]
|
|
||||||
enum Untagged {
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Unit,
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
NewType(Value),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Struct { i: i32, b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extend_enum_untagged() -> TestResult {
|
|
||||||
test_default_generated_schema::<Untagged>("extend_enum_untagged")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(tag = "t", content = "c", extend("foo" = "bar"))]
|
|
||||||
enum Adjacent {
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Unit,
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
NewType(Value),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Tuple(i32, bool),
|
|
||||||
#[schemars(extend("foo" = "bar"))]
|
|
||||||
Struct { i: i32, b: bool },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn extend_enum_adjacent() -> TestResult {
|
|
||||||
test_default_generated_schema::<Adjacent>("extend_enum_adjacent")
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use std::ffi::{OsStr, OsString};
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct OsStrings {
|
|
||||||
owned: OsString,
|
|
||||||
borrowed: &'static OsStr,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn os_strings() -> TestResult {
|
|
||||||
test_default_generated_schema::<OsStrings>("os_strings")
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Flat {
|
|
||||||
f: f32,
|
|
||||||
b: bool,
|
|
||||||
s: String,
|
|
||||||
#[serde(default)]
|
|
||||||
os: String,
|
|
||||||
v: Vec<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(rename = "Flat")]
|
|
||||||
struct Deep1 {
|
|
||||||
f: f32,
|
|
||||||
#[schemars(flatten)]
|
|
||||||
deep2: Deep2,
|
|
||||||
v: Vec<i32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::option_option, dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Deep2 {
|
|
||||||
b: bool,
|
|
||||||
#[serde(flatten)]
|
|
||||||
deep3: Deep3,
|
|
||||||
#[serde(flatten)]
|
|
||||||
deep4: Box<Option<Option<Box<Deep4>>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Deep3 {
|
|
||||||
s: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct Deep4 {
|
|
||||||
#[serde(default)]
|
|
||||||
os: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flat_schema() -> TestResult {
|
|
||||||
test_default_generated_schema::<Flat>("flatten")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flattened_schema() -> TestResult {
|
|
||||||
// intentionally using the same file as test_flat_schema, as the schema should be identical
|
|
||||||
test_default_generated_schema::<Deep1>("flatten")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct FlattenValue {
|
|
||||||
flag: bool,
|
|
||||||
#[serde(flatten)]
|
|
||||||
value: Value,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[schemars(rename = "FlattenValue")]
|
|
||||||
struct FlattenMap {
|
|
||||||
flag: bool,
|
|
||||||
#[serde(flatten)]
|
|
||||||
value: BTreeMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flattened_value() -> TestResult {
|
|
||||||
test_default_generated_schema::<FlattenValue>("flattened_value")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flattened_map() -> TestResult {
|
|
||||||
// intentionally using the same file as test_flattened_value, as the schema should be identical
|
|
||||||
test_default_generated_schema::<FlattenMap>("flattened_value")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct OuterAllowUnknownFields {
|
|
||||||
pub outer_field: bool,
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub middle: MiddleDenyUnknownFields,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct MiddleDenyUnknownFields {
|
|
||||||
pub middle_field: bool,
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub inner: InnerAllowUnknownFields,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct InnerAllowUnknownFields {
|
|
||||||
pub inner_field: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_flattened_struct_deny_unknown_fields() -> TestResult {
|
|
||||||
test_default_generated_schema::<(OuterAllowUnknownFields, MiddleDenyUnknownFields)>(
|
|
||||||
"test_flattened_struct_deny_unknown_fields",
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,94 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::generate::{SchemaGenerator, SchemaSettings};
|
|
||||||
use serde::Serialize;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct MyStruct {
|
|
||||||
pub my_int: i32,
|
|
||||||
pub my_bool: bool,
|
|
||||||
pub my_nullable_enum: Option<MyEnum>,
|
|
||||||
pub my_inner_struct: MyInnerStruct,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub skip: i32,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub skip_if_none: Option<MyEnum>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct MyInnerStruct {
|
|
||||||
pub my_map: HashMap<String, f64>,
|
|
||||||
pub my_vec: Vec<&'static str>,
|
|
||||||
pub my_empty_map: HashMap<String, f64>,
|
|
||||||
pub my_empty_vec: Vec<&'static str>,
|
|
||||||
pub my_tuple: (char, u8),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub enum MyEnum {
|
|
||||||
StringNewType(String),
|
|
||||||
StructVariant { floats: Vec<f32> },
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_value() -> MyStruct {
|
|
||||||
let mut value = MyStruct {
|
|
||||||
my_int: 123,
|
|
||||||
my_bool: true,
|
|
||||||
my_nullable_enum: None,
|
|
||||||
my_inner_struct: MyInnerStruct {
|
|
||||||
my_map: HashMap::new(),
|
|
||||||
my_vec: vec!["hello", "world"],
|
|
||||||
my_empty_map: HashMap::new(),
|
|
||||||
my_empty_vec: vec![],
|
|
||||||
my_tuple: ('💩', 42),
|
|
||||||
},
|
|
||||||
skip: 123,
|
|
||||||
skip_if_none: None,
|
|
||||||
};
|
|
||||||
value.my_inner_struct.my_map.insert(String::new(), 0.0);
|
|
||||||
value
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn schema_from_value_matches_draft07() -> TestResult {
|
|
||||||
let generator = SchemaSettings::draft07().into_generator();
|
|
||||||
let actual = generator.into_root_schema_for_value(&make_value())?;
|
|
||||||
|
|
||||||
test_schema(&actual, "from_value_draft07")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn schema_from_value_matches_2019_09() -> TestResult {
|
|
||||||
let generator = SchemaSettings::draft2019_09().into_generator();
|
|
||||||
let actual = generator.into_root_schema_for_value(&make_value())?;
|
|
||||||
|
|
||||||
test_schema(&actual, "from_value_2019_09")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn schema_from_value_matches_openapi3() -> TestResult {
|
|
||||||
let generator = SchemaSettings::openapi3().into_generator();
|
|
||||||
let actual = generator.into_root_schema_for_value(&make_value())?;
|
|
||||||
|
|
||||||
test_schema(&actual, "from_value_openapi3")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn schema_from_json_value() -> TestResult {
|
|
||||||
let generator = SchemaGenerator::default();
|
|
||||||
let actual = generator.into_root_schema_for_value(&serde_json::json!({
|
|
||||||
"zero": 0,
|
|
||||||
"one": 1,
|
|
||||||
"minusOne": -1,
|
|
||||||
"zeroPointZero": 0.0,
|
|
||||||
"bool": true,
|
|
||||||
"null": null,
|
|
||||||
"object": {
|
|
||||||
"array": ["foo", "bar"]
|
|
||||||
},
|
|
||||||
}))?;
|
|
||||||
|
|
||||||
test_schema(&actual, "from_json_value")
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
const MIN: u32 = 1;
|
|
||||||
const MAX: u32 = 1000;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct Struct {
|
|
||||||
#[garde(range(min = 0.01, max = 100))]
|
|
||||||
min_max: f32,
|
|
||||||
#[garde(range(min = MIN, max = MAX))]
|
|
||||||
min_max2: f32,
|
|
||||||
#[garde(pattern(r"^[Hh]ello\b"))]
|
|
||||||
regex_str1: String,
|
|
||||||
#[garde(contains(concat!("sub","string...")))]
|
|
||||||
contains_str1: String,
|
|
||||||
#[garde(email)]
|
|
||||||
email_address: String,
|
|
||||||
#[garde(url)]
|
|
||||||
homepage: String,
|
|
||||||
#[garde(length(min = 1, max = 100))]
|
|
||||||
non_empty_str: String,
|
|
||||||
#[garde(length(min = MIN, max = MAX))]
|
|
||||||
non_empty_str2: String,
|
|
||||||
#[garde(length(equal = 2))]
|
|
||||||
pair: Vec<i32>,
|
|
||||||
#[garde(required)]
|
|
||||||
required_option: Option<bool>,
|
|
||||||
#[garde(required)]
|
|
||||||
#[serde(flatten)]
|
|
||||||
required_flattened: Option<Inner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct Inner {
|
|
||||||
x: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn garde() -> TestResult {
|
|
||||||
test_default_generated_schema::<Struct>("garde")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct Struct2 {
|
|
||||||
#[schemars(range(min = 0.01, max = 100))]
|
|
||||||
min_max: f32,
|
|
||||||
#[schemars(range(min = MIN, max = MAX))]
|
|
||||||
min_max2: f32,
|
|
||||||
#[schemars(pattern(r"^[Hh]ello\b"))]
|
|
||||||
regex_str1: String,
|
|
||||||
#[schemars(contains(concat!("sub","string...")))]
|
|
||||||
contains_str1: String,
|
|
||||||
#[schemars(email)]
|
|
||||||
email_address: String,
|
|
||||||
#[schemars(url)]
|
|
||||||
homepage: String,
|
|
||||||
#[schemars(length(min = 1, max = 100))]
|
|
||||||
non_empty_str: String,
|
|
||||||
#[schemars(length(min = MIN, max = MAX))]
|
|
||||||
non_empty_str2: String,
|
|
||||||
#[schemars(length(equal = 2))]
|
|
||||||
pair: Vec<i32>,
|
|
||||||
#[schemars(required)]
|
|
||||||
required_option: Option<bool>,
|
|
||||||
#[schemars(required)]
|
|
||||||
#[serde(flatten)]
|
|
||||||
required_flattened: Option<Inner>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn garde_schemars_attrs() -> TestResult {
|
|
||||||
test_default_generated_schema::<Struct2>("garde_schemars_attrs")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct Tuple(
|
|
||||||
#[garde(range(max = 10))] u8,
|
|
||||||
#[garde(required)] Option<bool>,
|
|
||||||
);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn garde_tuple() -> TestResult {
|
|
||||||
test_default_generated_schema::<Tuple>("garde_tuple")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
pub struct NewType(#[garde(range(max = 10))] u8);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn garde_newtype() -> TestResult {
|
|
||||||
test_default_generated_schema::<NewType>("garde_newtype")
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
mod util;
|
|
||||||
use std::collections::hash_map::RandomState;
|
|
||||||
|
|
||||||
use indexmap2::{IndexMap, IndexSet};
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct IndexMapTypes {
|
|
||||||
map: IndexMap<i32, bool, RandomState>,
|
|
||||||
set: IndexSet<isize, RandomState>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn indexmap_types() -> TestResult {
|
|
||||||
test_default_generated_schema::<IndexMapTypes>("indexmap")
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
mod util;
|
|
||||||
use schemars::generate::SchemaSettings;
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct MyJob {
|
|
||||||
spec: MyJobSpec,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct MyJobSpec {
|
|
||||||
replicas: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn struct_normal() -> TestResult {
|
|
||||||
let mut settings = SchemaSettings::default();
|
|
||||||
settings.inline_subschemas = true;
|
|
||||||
test_generated_schema::<MyJob>("inline-subschemas", settings)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct RecursiveOuter {
|
|
||||||
direct: Option<Box<RecursiveOuter>>,
|
|
||||||
indirect: Option<Box<RecursiveInner>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(JsonSchema)]
|
|
||||||
struct RecursiveInner {
|
|
||||||
recursive: RecursiveOuter,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn struct_recursive() -> TestResult {
|
|
||||||
let mut settings = SchemaSettings::default();
|
|
||||||
settings.inline_subschemas = true;
|
|
||||||
test_generated_schema::<RecursiveOuter>("inline-subschemas-recursive", settings)
|
|
||||||
}
|
|
36
schemars/tests/integration/arrayvec.rs
Normal file
36
schemars/tests/integration/arrayvec.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use arrayvec07::{ArrayString, ArrayVec};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arrayvec07() {
|
||||||
|
test!(ArrayVec<i32, 8>)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
ArrayVec::from_iter([]),
|
||||||
|
ArrayVec::from_iter([1, 2, 3, 4, 5, 6, 7, 8]),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(
|
||||||
|
(0..16).map(|len| Value::Array((0..len).map(Value::from).collect())),
|
||||||
|
)
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values_except(
|
||||||
|
is_array_of_u64,
|
||||||
|
"FIXME schema allows out-of-range positive integers",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arrayvec07_arraystring() {
|
||||||
|
test!(ArrayString<8>)
|
||||||
|
.assert_identical::<String>()
|
||||||
|
.assert_allows_ser_roundtrip(["".try_into().unwrap(), "12345678".try_into().unwrap()])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values_except(
|
||||||
|
Value::is_string,
|
||||||
|
"There's not a good way to express UTF-8 byte length in JSON schema, so schema ignores the ArrayString's capacity.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_array_of_u64(value: &Value) -> bool {
|
||||||
|
value
|
||||||
|
.as_array()
|
||||||
|
.is_some_and(|a| a.iter().all(Value::is_u64))
|
||||||
|
}
|
|
@ -1,9 +1,6 @@
|
||||||
mod util;
|
use crate::prelude::*;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
struct MyIterator;
|
struct MyIterator;
|
||||||
|
|
||||||
impl Iterator for MyIterator {
|
impl Iterator for MyIterator {
|
||||||
|
@ -16,7 +13,7 @@ impl Iterator for MyIterator {
|
||||||
|
|
||||||
// The default trait bounds would require T to implement JsonSchema,
|
// The default trait bounds would require T to implement JsonSchema,
|
||||||
// which MyIterator does not.
|
// which MyIterator does not.
|
||||||
#[derive(JsonSchema)]
|
#[derive(JsonSchema, Serialize, Deserialize)]
|
||||||
#[schemars(bound = "T::Item: JsonSchema", rename = "MyContainer")]
|
#[schemars(bound = "T::Item: JsonSchema", rename = "MyContainer")]
|
||||||
pub struct MyContainer<T>
|
pub struct MyContainer<T>
|
||||||
where
|
where
|
||||||
|
@ -27,6 +24,12 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn manual_bound_set() -> TestResult {
|
fn manual_bound_set() {
|
||||||
test_default_generated_schema::<MyContainer<MyIterator>>("bound")
|
test!(MyContainer<MyIterator>)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([MyContainer {
|
||||||
|
associated: "test".to_owned(),
|
||||||
|
generic: PhantomData,
|
||||||
|
}])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
}
|
}
|
24
schemars/tests/integration/bytes.rs
Normal file
24
schemars/tests/integration/bytes.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use bytes1::{Bytes, BytesMut};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes() {
|
||||||
|
test!(Bytes)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([Bytes::new(), Bytes::from_iter([12; 34])])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values_except(
|
||||||
|
is_array_of_u64,
|
||||||
|
"FIXME schema allows out-of-range positive integers",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes_mut() {
|
||||||
|
test!(BytesMut).assert_identical::<Bytes>();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_array_of_u64(value: &Value) -> bool {
|
||||||
|
value
|
||||||
|
.as_array()
|
||||||
|
.is_some_and(|a| a.iter().all(Value::is_u64))
|
||||||
|
}
|
42
schemars/tests/integration/chrono.rs
Normal file
42
schemars/tests/integration/chrono.rs
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use chrono04::prelude::*;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Serialize, Deserialize)]
|
||||||
|
struct ChronoTypes {
|
||||||
|
weekday: Weekday,
|
||||||
|
date_time: DateTime<Utc>,
|
||||||
|
naive_date: NaiveDate,
|
||||||
|
naive_date_time: NaiveDateTime,
|
||||||
|
naive_time: NaiveTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn chrono() {
|
||||||
|
test!(ChronoTypes).assert_snapshot();
|
||||||
|
|
||||||
|
test!(Weekday)
|
||||||
|
.assert_allows_ser_roundtrip([Weekday::Mon])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
|
||||||
|
test!(DateTime<Utc>)
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
|
||||||
|
test!(NaiveDate)
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
|
||||||
|
test!(NaiveDateTime)
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values_except(
|
||||||
|
Value::is_string,
|
||||||
|
"Custom format 'partial-date-time', so arbitrary strings technically allowed by schema",
|
||||||
|
));
|
||||||
|
|
||||||
|
test!(NaiveTime)
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values_except(
|
||||||
|
Value::is_string,
|
||||||
|
"Custom format 'date-time', so arbitrary strings technically allowed by schema",
|
||||||
|
));
|
||||||
|
}
|
254
schemars/tests/integration/contract.rs
Normal file
254
schemars/tests/integration/contract.rs
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all(serialize = "SCREAMING-KEBAB-CASE"), deny_unknown_fields)]
|
||||||
|
struct StructDenyUnknownFields {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
read_only: bool,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
write_only: bool,
|
||||||
|
#[serde(default)]
|
||||||
|
default: bool,
|
||||||
|
#[serde(skip_serializing_if = "core::ops::Not::not")]
|
||||||
|
skip_serializing_if: bool,
|
||||||
|
#[serde(rename(serialize = "ser_renamed", deserialize = "de_renamed"))]
|
||||||
|
renamed: bool,
|
||||||
|
option: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct StructAllowUnknownFields {
|
||||||
|
#[serde(flatten)]
|
||||||
|
inner: StructDenyUnknownFields,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_deny_unknown_fields() {
|
||||||
|
test!(StructDenyUnknownFields)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
json!({ "write_only": false, "skip_serializing_if": false, "de_renamed": false }),
|
||||||
|
json!({ "write_only": true, "skip_serializing_if": true, "de_renamed": true, "default": true }),
|
||||||
|
json!({ "write_only": true, "skip_serializing_if": true, "de_renamed": true, "option": true }),
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
json!({ "skip_serializing_if": false, "de_renamed": false }),
|
||||||
|
json!({ "write_only": false, "de_renamed": false }),
|
||||||
|
json!({ "write_only": false, "skip_serializing_if": false }),
|
||||||
|
json!({ "write_only": true, "skip_serializing_if": true, "de_renamed": true, "unknown": true }),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_allow_unknown_fields() {
|
||||||
|
test!(StructAllowUnknownFields)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
json!({ "write_only": false, "skip_serializing_if": false, "de_renamed": false }),
|
||||||
|
json!({ "write_only": true, "skip_serializing_if": true, "de_renamed": true, "default": true }),
|
||||||
|
json!({ "write_only": true, "skip_serializing_if": true, "de_renamed": true, "option": true }),
|
||||||
|
json!({ "write_only": true, "skip_serializing_if": true, "de_renamed": true, "unknown": true }),
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
json!({ "skip_serializing_if": false, "de_renamed": false }),
|
||||||
|
json!({ "write_only": false, "de_renamed": false }),
|
||||||
|
json!({ "write_only": false, "skip_serializing_if": false }),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct TupleStruct(
|
||||||
|
String,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
bool,
|
||||||
|
String,
|
||||||
|
#[serde(skip_deserializing)] bool,
|
||||||
|
String,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tuple_struct() {
|
||||||
|
test!(TupleStruct)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_de_roundtrip([json!(["", true, "", ""])])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(
|
||||||
|
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
||||||
|
rename_all_fields(serialize = "PascalCase")
|
||||||
|
)]
|
||||||
|
enum ExternalEnum {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyUnit,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyUnit,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyStruct { s: String },
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyStruct { i: isize },
|
||||||
|
#[serde(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
||||||
|
RenamedUnit,
|
||||||
|
#[serde(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
||||||
|
RenamedStruct { b: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn externally_tagged_enum() {
|
||||||
|
test!(ExternalEnum)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
ExternalEnum::ReadOnlyUnit,
|
||||||
|
ExternalEnum::ReadOnlyStruct { s: "test".into() },
|
||||||
|
ExternalEnum::RenamedUnit,
|
||||||
|
ExternalEnum::RenamedStruct { b: true },
|
||||||
|
])
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
json!("WriteOnlyUnit"),
|
||||||
|
json!({ "WriteOnlyStruct": { "i": 123 } }),
|
||||||
|
json!("de_renamed_unit"),
|
||||||
|
json!({ "de_renamed_struct": { "b": true } }),
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
json!("READ-ONLY-UNIT"),
|
||||||
|
json!("ReadOnlyUnit"),
|
||||||
|
json!("ser_renamed_unit"),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(
|
||||||
|
tag = "tag",
|
||||||
|
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
||||||
|
rename_all_fields(serialize = "PascalCase")
|
||||||
|
)]
|
||||||
|
enum InternalEnum {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyUnit,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyUnit,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyStruct { s: String },
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyStruct { i: isize },
|
||||||
|
#[serde(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
||||||
|
RenamedUnit,
|
||||||
|
#[serde(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
||||||
|
RenamedStruct { b: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn internally_tagged_enum() {
|
||||||
|
test!(InternalEnum)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
InternalEnum::ReadOnlyUnit,
|
||||||
|
InternalEnum::ReadOnlyStruct { s: "test".into() },
|
||||||
|
InternalEnum::RenamedUnit,
|
||||||
|
InternalEnum::RenamedStruct { b: true },
|
||||||
|
])
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
json!({ "tag": "WriteOnlyUnit" }),
|
||||||
|
json!({ "tag": "WriteOnlyStruct", "i": 123 }),
|
||||||
|
json!({ "tag": "de_renamed_unit" }),
|
||||||
|
json!({ "tag": "de_renamed_struct", "b": true }),
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
json!({ "tag": "READ-ONLY-UNIT" }),
|
||||||
|
json!({ "tag": "ReadOnlyUnit" }),
|
||||||
|
json!({ "tag": "ser_renamed_unit" }),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(
|
||||||
|
tag = "tag",
|
||||||
|
content = "content",
|
||||||
|
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
||||||
|
rename_all_fields(serialize = "PascalCase")
|
||||||
|
)]
|
||||||
|
enum AdjacentEnum {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyUnit,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyUnit,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyStruct { s: String },
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyStruct { i: isize },
|
||||||
|
#[serde(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
||||||
|
RenamedUnit,
|
||||||
|
#[serde(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
||||||
|
RenamedStruct { b: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn adjacently_tagged_enum() {
|
||||||
|
test!(AdjacentEnum)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
AdjacentEnum::ReadOnlyUnit,
|
||||||
|
AdjacentEnum::ReadOnlyStruct { s: "test".into() },
|
||||||
|
AdjacentEnum::RenamedUnit,
|
||||||
|
AdjacentEnum::RenamedStruct { b: true },
|
||||||
|
])
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
json!({ "tag": "WriteOnlyUnit" }),
|
||||||
|
json!({ "tag": "WriteOnlyStruct", "content": { "i": 123 } }),
|
||||||
|
json!({ "tag": "de_renamed_unit" }),
|
||||||
|
json!({ "tag": "de_renamed_struct", "content": { "b": true } }),
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
json!({ "tag": "READ-ONLY-UNIT" }),
|
||||||
|
json!({ "tag": "ReadOnlyUnit" }),
|
||||||
|
json!({ "tag": "ser_renamed_unit" }),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(
|
||||||
|
untagged,
|
||||||
|
rename_all(serialize = "SCREAMING-KEBAB-CASE"),
|
||||||
|
rename_all_fields(serialize = "PascalCase")
|
||||||
|
)]
|
||||||
|
enum UntaggedEnum {
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyUnit,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyUnit,
|
||||||
|
#[serde(skip_deserializing)]
|
||||||
|
ReadOnlyStruct { s: String },
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
WriteOnlyStruct { i: isize },
|
||||||
|
#[serde(rename(serialize = "ser_renamed_unit", deserialize = "de_renamed_unit"))]
|
||||||
|
RenamedUnit,
|
||||||
|
#[serde(rename(serialize = "ser_renamed_struct", deserialize = "de_renamed_struct"))]
|
||||||
|
RenamedStruct { b: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn untagged_enum() {
|
||||||
|
test!(UntaggedEnum)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
UntaggedEnum::ReadOnlyUnit,
|
||||||
|
UntaggedEnum::ReadOnlyStruct { s: "test".into() },
|
||||||
|
UntaggedEnum::RenamedUnit,
|
||||||
|
UntaggedEnum::RenamedStruct { b: true },
|
||||||
|
])
|
||||||
|
.assert_allows_de_roundtrip([json!(null), json!({ "i": 123 }), json!({ "b": true })])
|
||||||
|
.assert_rejects_de([json!({ "s": "test" })])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
19
schemars/tests/integration/crate_alias.rs
Normal file
19
schemars/tests/integration/crate_alias.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use ::schemars as aliased_schemars;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(aliased_schemars::JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
#[schemars(crate = "aliased_schemars")]
|
||||||
|
struct MyStruct {
|
||||||
|
/// Is it ok with doc comments?
|
||||||
|
foo: i32,
|
||||||
|
#[schemars(extend("x-test" = "...and extensions?"))]
|
||||||
|
bar: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn crate_alias() {
|
||||||
|
test!(MyStruct)
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
19
schemars/tests/integration/decimal.rs
Normal file
19
schemars/tests/integration/decimal.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decimal_types() {
|
||||||
|
#[cfg(feature = "rust_decimal1")]
|
||||||
|
test!(rust_decimal1::Decimal)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
|
||||||
|
#[cfg(feature = "bigdecimal04")]
|
||||||
|
test!(bigdecimal04::BigDecimal)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
|
||||||
|
#[cfg(all(feature = "rust_decimal1", feature = "bigdecimal04"))]
|
||||||
|
test!(bigdecimal04::BigDecimal).assert_identical::<rust_decimal1::Decimal>();
|
||||||
|
}
|
95
schemars/tests/integration/default.rs
Normal file
95
schemars/tests/integration/default.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
#[serde(default)]
|
||||||
|
struct MyStruct {
|
||||||
|
integer: u32,
|
||||||
|
boolean: bool,
|
||||||
|
option_string: Option<String>,
|
||||||
|
#[serde(skip_serializing_if = "str::is_empty")]
|
||||||
|
string_skip_empty: String,
|
||||||
|
#[serde(with = "struct_2_as_str")]
|
||||||
|
#[schemars(with = "str", pattern(r"^\d+ (true|false)$"))]
|
||||||
|
struct2: MyStruct2,
|
||||||
|
#[serde(skip_serializing)]
|
||||||
|
not_serialize: NotSerialize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
#[serde(default = "ten_and_true")]
|
||||||
|
struct MyStruct2 {
|
||||||
|
#[serde(default = "six")]
|
||||||
|
integer: u32,
|
||||||
|
boolean: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema, Deserialize, Default)]
|
||||||
|
struct NotSerialize(i8);
|
||||||
|
|
||||||
|
mod struct_2_as_str {
|
||||||
|
use super::MyStruct2;
|
||||||
|
|
||||||
|
pub(super) fn serialize<S>(value: &MyStruct2, ser: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
ser.collect_str(&format_args!("{} {}", value.integer, value.boolean))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn deserialize<'de, D>(deser: D) -> Result<MyStruct2, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use serde::de::{Deserialize, Error};
|
||||||
|
let error = || Error::custom("invalid string");
|
||||||
|
|
||||||
|
let (i, b) = <&str>::deserialize(deser)?
|
||||||
|
.split_once(' ')
|
||||||
|
.ok_or_else(error)?;
|
||||||
|
|
||||||
|
Ok(MyStruct2 {
|
||||||
|
integer: i.parse().map_err(|_| error())?,
|
||||||
|
boolean: b.parse().map_err(|_| error())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ten_and_true() -> MyStruct2 {
|
||||||
|
MyStruct2 {
|
||||||
|
integer: 10,
|
||||||
|
boolean: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn six() -> u32 {
|
||||||
|
6
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_fields() {
|
||||||
|
test!(MyStruct)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
MyStruct::default(),
|
||||||
|
MyStruct {
|
||||||
|
integer: 123,
|
||||||
|
boolean: true,
|
||||||
|
option_string: Some("test".into()),
|
||||||
|
string_skip_empty: "test".into(),
|
||||||
|
struct2: ten_and_true(),
|
||||||
|
not_serialize: NotSerialize(42),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
json!({}),
|
||||||
|
json!({ "not_serialize": 127 })
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
json!({ "not_serialize": "a string" })
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values_except(
|
||||||
|
Value::is_array,
|
||||||
|
"structs with `#derive(Deserialize)` can technically be deserialized from sequences, but that's not intended to be used via JSON, so schemars ignores it",
|
||||||
|
));
|
||||||
|
}
|
69
schemars/tests/integration/deprecated.rs
Normal file
69
schemars/tests/integration/deprecated.rs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Default, Serialize, Deserialize)]
|
||||||
|
#[deprecated]
|
||||||
|
struct DeprecatedStruct {
|
||||||
|
foo: i32,
|
||||||
|
#[deprecated]
|
||||||
|
bar: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
#[test]
|
||||||
|
fn deprecated_struct() {
|
||||||
|
test!(DeprecatedStruct)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.custom(|schema, _| {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/deprecated"),
|
||||||
|
Some(&Value::Bool(true)),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/properties/bar/deprecated"),
|
||||||
|
Some(&Value::Bool(true)),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Default, Serialize, Deserialize)]
|
||||||
|
#[deprecated]
|
||||||
|
enum DeprecatedEnum {
|
||||||
|
#[default]
|
||||||
|
Unit,
|
||||||
|
#[deprecated]
|
||||||
|
DeprecatedUnitVariant,
|
||||||
|
#[deprecated]
|
||||||
|
DeprecatedStructVariant {
|
||||||
|
foo: i32,
|
||||||
|
#[deprecated]
|
||||||
|
deprecated_field: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn deprecated_enum() {
|
||||||
|
test!(DeprecatedEnum)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.custom(|schema, _| {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/deprecated"),
|
||||||
|
Some(&Value::Bool(true)),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/1/deprecated"),
|
||||||
|
Some(&Value::Bool(true)),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/2/deprecated"),
|
||||||
|
Some(&Value::Bool(true)),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/2/properties/DeprecatedStructVariant/properties/deprecated_field/deprecated"),
|
||||||
|
Some(&Value::Bool(true)),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
mod util;
|
use crate::prelude::*;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[derive(JsonSchema)]
|
#[derive(JsonSchema)]
|
||||||
|
@ -24,6 +22,11 @@ struct MyStruct {
|
||||||
#[derive(JsonSchema)]
|
#[derive(JsonSchema)]
|
||||||
struct MyUnitStruct;
|
struct MyUnitStruct;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn doc_comments_struct() {
|
||||||
|
test!(MyStruct).assert_snapshot();
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[doc = " # This is the enum's title "]
|
#[doc = " # This is the enum's title "]
|
||||||
#[doc = " This is "]
|
#[doc = " This is "]
|
||||||
|
@ -55,13 +58,8 @@ enum MyEnum {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn doc_comments_struct() -> TestResult {
|
fn doc_comments_enum() {
|
||||||
test_default_generated_schema::<MyStruct>("doc_comments_struct")
|
test!(MyEnum).assert_snapshot();
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn doc_comments_enum() -> TestResult {
|
|
||||||
test_default_generated_schema::<MyEnum>("doc_comments_enum")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # OverrideDocs struct
|
/// # OverrideDocs struct
|
||||||
|
@ -82,6 +80,6 @@ struct OverrideDocs {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn doc_comments_override() -> TestResult {
|
fn doc_comments_override() {
|
||||||
test_default_generated_schema::<OverrideDocs>("doc_comments_override")
|
test!(OverrideDocs).assert_snapshot();
|
||||||
}
|
}
|
14
schemars/tests/integration/either.rs
Normal file
14
schemars/tests/integration/either.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use either1::Either;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn either() {
|
||||||
|
test!(Either<i32, Either<bool, ()>>)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
Either::Left(123),
|
||||||
|
Either::Right(Either::Left(true)),
|
||||||
|
Either::Right(Either::Right(())),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
37
schemars/tests/integration/enum_repr.rs
Normal file
37
schemars/tests/integration/enum_repr.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use schemars::JsonSchema_repr;
|
||||||
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
|
||||||
|
#[derive(JsonSchema_repr, Deserialize_repr, Serialize_repr)]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[serde(rename = "EnumWithReprAttr")]
|
||||||
|
/// Description from comment
|
||||||
|
pub enum Enum {
|
||||||
|
Zero,
|
||||||
|
One,
|
||||||
|
Five = 5,
|
||||||
|
Six,
|
||||||
|
Three = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enum_repr() {
|
||||||
|
test!(Enum)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([Enum::Zero, Enum::One, Enum::Five, Enum::Six, Enum::Three])
|
||||||
|
.assert_allows_de_roundtrip([
|
||||||
|
Value::from(0),
|
||||||
|
Value::from(1),
|
||||||
|
Value::from(5),
|
||||||
|
Value::from(6),
|
||||||
|
Value::from(3),
|
||||||
|
])
|
||||||
|
.assert_rejects_de([
|
||||||
|
Value::from("Zero"),
|
||||||
|
Value::from("One"),
|
||||||
|
Value::from("Five"),
|
||||||
|
Value::from("Six"),
|
||||||
|
Value::from("Three"),
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
360
schemars/tests/integration/enums.rs
Normal file
360
schemars/tests/integration/enums.rs
Normal file
|
@ -0,0 +1,360 @@
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct UnitStruct;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct Struct {
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
enum External {
|
||||||
|
UnitOne,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
UnitStructNewType(UnitStruct),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct {
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
},
|
||||||
|
Tuple(i32, bool),
|
||||||
|
UnitTwo,
|
||||||
|
#[serde(with = "unit_variant_as_u64")]
|
||||||
|
#[schemars(with = "u64")]
|
||||||
|
UnitAsInt,
|
||||||
|
#[serde(with = "tuple_variant_as_str")]
|
||||||
|
#[schemars(schema_with = "tuple_variant_as_str::json_schema")]
|
||||||
|
TupleAsStr(i32, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl External {
|
||||||
|
fn values() -> impl IntoIterator<Item = Self> {
|
||||||
|
[
|
||||||
|
Self::UnitOne,
|
||||||
|
Self::StringMap(
|
||||||
|
[("hello".to_owned(), "world".to_owned())]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
Self::UnitStructNewType(UnitStruct),
|
||||||
|
Self::StructNewType(Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
}),
|
||||||
|
Self::Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
},
|
||||||
|
Self::Tuple(456, false),
|
||||||
|
Self::UnitTwo,
|
||||||
|
Self::UnitAsInt,
|
||||||
|
Self::TupleAsStr(789, true),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "tag")]
|
||||||
|
enum Internal {
|
||||||
|
UnitOne,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
UnitStructNewType(UnitStruct),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct { foo: i32, bar: bool },
|
||||||
|
// Internally-tagged enums don't support tuple variants
|
||||||
|
// Tuple(i32, bool),
|
||||||
|
UnitTwo,
|
||||||
|
// Internally-tagged enum variants don't support non-object "payloads"
|
||||||
|
// #[serde(with = "unit_variant_as_u64")]
|
||||||
|
// #[schemars(with = "u64")]
|
||||||
|
// UnitAsInt,
|
||||||
|
// Internally-tagged enums don't support tuple variants
|
||||||
|
// #[serde(with = "tuple_variant_as_str")]
|
||||||
|
// #[schemars(schema_with = "tuple_variant_as_str::json_schema")]
|
||||||
|
// TupleAsStr(i32, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Internal {
|
||||||
|
fn values() -> impl IntoIterator<Item = Self> {
|
||||||
|
[
|
||||||
|
Self::UnitOne,
|
||||||
|
Self::StringMap(
|
||||||
|
[("hello".to_owned(), "world".to_owned())]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
Self::UnitStructNewType(UnitStruct),
|
||||||
|
Self::StructNewType(Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
}),
|
||||||
|
Self::Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
},
|
||||||
|
// Self::Tuple(456, false),
|
||||||
|
Self::UnitTwo,
|
||||||
|
// Self::UnitAsInt,
|
||||||
|
// Self::TupleAsStr(789, true),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "tag", content = "content")]
|
||||||
|
enum Adjacent {
|
||||||
|
UnitOne,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
UnitStructNewType(UnitStruct),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct {
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
},
|
||||||
|
Tuple(i32, bool),
|
||||||
|
UnitTwo,
|
||||||
|
#[serde(with = "unit_variant_as_u64")]
|
||||||
|
#[schemars(with = "u64")]
|
||||||
|
UnitAsInt,
|
||||||
|
#[serde(with = "tuple_variant_as_str")]
|
||||||
|
#[schemars(schema_with = "tuple_variant_as_str::json_schema")]
|
||||||
|
TupleAsStr(i32, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Adjacent {
|
||||||
|
fn values() -> impl IntoIterator<Item = Self> {
|
||||||
|
[
|
||||||
|
Self::UnitOne,
|
||||||
|
Self::StringMap(
|
||||||
|
[("hello".to_owned(), "world".to_owned())]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
Self::UnitStructNewType(UnitStruct),
|
||||||
|
Self::StructNewType(Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
}),
|
||||||
|
Self::Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
},
|
||||||
|
Self::Tuple(456, false),
|
||||||
|
Self::UnitTwo,
|
||||||
|
Self::UnitAsInt,
|
||||||
|
Self::TupleAsStr(789, true),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum Untagged {
|
||||||
|
UnitOne,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
UnitStructNewType(UnitStruct),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct {
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
},
|
||||||
|
Tuple(i32, bool),
|
||||||
|
UnitTwo,
|
||||||
|
#[serde(with = "unit_variant_as_u64")]
|
||||||
|
#[schemars(with = "u64")]
|
||||||
|
UnitAsInt,
|
||||||
|
#[serde(with = "tuple_variant_as_str")]
|
||||||
|
#[schemars(schema_with = "tuple_variant_as_str::json_schema")]
|
||||||
|
TupleAsStr(i32, bool),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Untagged {
|
||||||
|
fn values() -> impl IntoIterator<Item = Self> {
|
||||||
|
[
|
||||||
|
Self::UnitOne,
|
||||||
|
Self::StringMap(
|
||||||
|
[("hello".to_owned(), "world".to_owned())]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
Self::UnitStructNewType(UnitStruct),
|
||||||
|
Self::StructNewType(Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
}),
|
||||||
|
Self::Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
},
|
||||||
|
Self::Tuple(456, false),
|
||||||
|
Self::UnitTwo,
|
||||||
|
Self::UnitAsInt,
|
||||||
|
Self::TupleAsStr(789, true),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod unit_variant_as_u64 {
|
||||||
|
pub(super) fn serialize<S>(ser: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
ser.serialize_u64(42)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn deserialize<'de, D>(deser: D) -> Result<(), D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use serde::de::Deserialize;
|
||||||
|
|
||||||
|
u64::deserialize(deser).map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod tuple_variant_as_str {
|
||||||
|
pub(super) fn serialize<S>(i: &i32, b: &bool, ser: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
ser.collect_str(&format_args!("{i} {b}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn deserialize<'de, D>(deser: D) -> Result<(i32, bool), D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
use serde::de::{Deserialize, Error};
|
||||||
|
let error = || Error::custom("invalid string");
|
||||||
|
|
||||||
|
let (i, b) = <&str>::deserialize(deser)?
|
||||||
|
.split_once(' ')
|
||||||
|
.ok_or_else(error)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
i.parse().map_err(|_| error())?,
|
||||||
|
b.parse().map_err(|_| error())?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
|
||||||
|
schemars::json_schema!({
|
||||||
|
"type": "string",
|
||||||
|
"pattern": r"^\d+ (true|false)$"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn externally_tagged_enum() {
|
||||||
|
test!(External)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(External::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn internally_tagged_enum() {
|
||||||
|
test!(Internal)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Internal::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn adjacently_tagged_enum() {
|
||||||
|
test!(Adjacent)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Adjacent::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn untagged_enum() {
|
||||||
|
test!(Untagged)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Untagged::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Serialize, Deserialize)]
|
||||||
|
enum NoVariants {}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_variants() {
|
||||||
|
test!(NoVariants)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_rejects_de(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all_fields = "UPPERCASE", rename_all = "snake_case")]
|
||||||
|
enum Renamed {
|
||||||
|
StructVariant {
|
||||||
|
field: String,
|
||||||
|
},
|
||||||
|
#[serde(rename = "custom name variant")]
|
||||||
|
RenamedStructVariant {
|
||||||
|
#[serde(rename = "custom name field")]
|
||||||
|
field: String,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn renamed() {
|
||||||
|
test!(Renamed)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
Renamed::StructVariant {
|
||||||
|
field: "foo".to_owned(),
|
||||||
|
},
|
||||||
|
Renamed::RenamedStructVariant {
|
||||||
|
field: "bar".to_owned(),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.assert_rejects_de(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
enum SoundOfMusic {
|
||||||
|
/// # A deer
|
||||||
|
///
|
||||||
|
/// A female deer
|
||||||
|
Do,
|
||||||
|
/// A drop of golden sun
|
||||||
|
Re,
|
||||||
|
/// A name I call myself
|
||||||
|
Mi,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unit_variants_with_doc_comments() {
|
||||||
|
test!(SoundOfMusic)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([SoundOfMusic::Do, SoundOfMusic::Re, SoundOfMusic::Mi])
|
||||||
|
.assert_rejects_de(arbitrary_values())
|
||||||
|
.custom(|schema, _| {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/0/title"),
|
||||||
|
Some(&("A deer".into())),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/0/description"),
|
||||||
|
Some(&("A female deer".into())),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/1/description"),
|
||||||
|
Some(&("A drop of golden sun".into())),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/oneOf/2/description"),
|
||||||
|
Some(&("A name I call myself".into())),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue