parent
092dc17ae4
commit
a479e6cc0e
239 changed files with 5780 additions and 4883 deletions
4
.github/workflows/ci.yml
vendored
4
.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
|
||||||
|
|
|
@ -6,6 +6,15 @@
|
||||||
|
|
||||||
- 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)
|
- 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
|
||||||
|
|
||||||
|
- ⚠️ MSRV is now 1.70 ⚠️
|
||||||
|
|
||||||
|
### 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
|
||||||
|
|
1146
Cargo.lock
generated
1146
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
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ 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.15", optional = true, path = "../schemars_derive" }
|
||||||
|
@ -37,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.19.0", 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"]
|
||||||
|
@ -59,62 +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 = "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"]
|
||||||
|
|
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;
|
||||||
|
|
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> {
|
||||||
|
|
|
@ -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,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,184 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
||||||
"title": "Adjacent",
|
|
||||||
"oneOf": [
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "UnitOne"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "StringMap"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "object",
|
|
||||||
"additionalProperties": {
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "UnitStructNewType"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"$ref": "#/$defs/UnitStruct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "StructNewType"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"$ref": "#/$defs/Struct"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Struct"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"bar": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"foo",
|
|
||||||
"bar"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "Tuple"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "array",
|
|
||||||
"prefixItems": [
|
|
||||||
{
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"minItems": 2,
|
|
||||||
"maxItems": 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "UnitTwo"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"t": {
|
|
||||||
"type": "string",
|
|
||||||
"const": "WithInt"
|
|
||||||
},
|
|
||||||
"c": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"t",
|
|
||||||
"c"
|
|
||||||
],
|
|
||||||
"additionalProperties": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"$defs": {
|
|
||||||
"UnitStruct": {
|
|
||||||
"type": "null"
|
|
||||||
},
|
|
||||||
"Struct": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"foo": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
},
|
|
||||||
"bar": {
|
|
||||||
"type": "boolean"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"foo",
|
|
||||||
"bar"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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,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,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,25 +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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"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())),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
162
schemars/tests/integration/enums_deny_unknown_fields.rs
Normal file
162
schemars/tests/integration/enums_deny_unknown_fields.rs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
macro_rules! fn_values {
|
||||||
|
() => {
|
||||||
|
fn values() -> impl IntoIterator<Item = Self> {
|
||||||
|
[
|
||||||
|
Self::Unit,
|
||||||
|
Self::StringMap(
|
||||||
|
[("hello".to_owned(), "world".to_owned())]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
Self::StructNewType(Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
}),
|
||||||
|
Self::Struct {
|
||||||
|
foo: 123,
|
||||||
|
bar: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct Struct {
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
enum External {
|
||||||
|
Unit,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct { foo: i32, bar: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl External {
|
||||||
|
fn_values!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "tag", deny_unknown_fields)]
|
||||||
|
enum Internal {
|
||||||
|
Unit,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct { foo: i32, bar: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Internal {
|
||||||
|
fn_values!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(tag = "tag", content = "content", deny_unknown_fields)]
|
||||||
|
enum Adjacent {
|
||||||
|
Unit,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct { foo: i32, bar: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Adjacent {
|
||||||
|
fn_values!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(untagged, deny_unknown_fields)]
|
||||||
|
enum Untagged {
|
||||||
|
Unit,
|
||||||
|
StringMap(BTreeMap<String, String>),
|
||||||
|
StructNewType(Struct),
|
||||||
|
Struct { foo: i32, bar: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Untagged {
|
||||||
|
fn_values!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn externally_tagged_enum() {
|
||||||
|
test!(External)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(External::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_rejects_de([json!({
|
||||||
|
"Struct": {
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
}
|
||||||
|
})])
|
||||||
|
.assert_allows_de_roundtrip([json!({
|
||||||
|
"StructNewType": {
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
}
|
||||||
|
})]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn internally_tagged_enum() {
|
||||||
|
test!(Internal)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Internal::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_rejects_de([json!({
|
||||||
|
"tag": "Struct",
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
})])
|
||||||
|
.assert_allows_de_roundtrip([json!({
|
||||||
|
"tag": "StructNewType",
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
})]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn adjacently_tagged_enum() {
|
||||||
|
test!(Adjacent)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Adjacent::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_rejects_de([json!({
|
||||||
|
"tag": "Struct",
|
||||||
|
"content": {
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
}
|
||||||
|
})])
|
||||||
|
.assert_allows_de_roundtrip([json!({
|
||||||
|
"tag": "StructNewType",
|
||||||
|
"content": {
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
}
|
||||||
|
})]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn untagged_enum() {
|
||||||
|
test!(Untagged)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Untagged::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_allows_de_roundtrip([json!({
|
||||||
|
"foo": 123,
|
||||||
|
"bar": true,
|
||||||
|
"extra": null
|
||||||
|
})]);
|
||||||
|
}
|
135
schemars/tests/integration/enums_flattened.rs
Normal file
135
schemars/tests/integration/enums_flattened.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use schemars::generate::SchemaSettings;
|
||||||
|
|
||||||
|
macro_rules! fn_values {
|
||||||
|
() => {
|
||||||
|
fn values() -> impl IntoIterator<Item = Self> {
|
||||||
|
[
|
||||||
|
Self {
|
||||||
|
f: 1.23,
|
||||||
|
e1: Enum1::B(true),
|
||||||
|
e2: Enum2::F(4.56),
|
||||||
|
e3: Enum3::S2("abc".into()),
|
||||||
|
e4: Enum4::U2(789),
|
||||||
|
e5: Enum5::B3(false),
|
||||||
|
},
|
||||||
|
Self {
|
||||||
|
f: 9.87,
|
||||||
|
e1: Enum1::S("def".into()),
|
||||||
|
e2: Enum2::U(654),
|
||||||
|
e3: Enum3::B2(true),
|
||||||
|
e4: Enum4::F2(3.21),
|
||||||
|
e5: Enum5::S3("ghi".into()),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
enum Enum1 {
|
||||||
|
B(bool),
|
||||||
|
S(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
enum Enum2 {
|
||||||
|
U(u32),
|
||||||
|
F(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
enum Enum3 {
|
||||||
|
B2(bool),
|
||||||
|
S2(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
enum Enum4 {
|
||||||
|
U2(u32),
|
||||||
|
F2(f64),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
enum Enum5 {
|
||||||
|
B3(bool),
|
||||||
|
S3(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct Container {
|
||||||
|
f: f32,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e1: Enum1,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e2: Enum2,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e3: Enum3,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e4: Enum4,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e5: Enum5,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Container {
|
||||||
|
fn_values!();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct ContainerDenyUnknownFields {
|
||||||
|
f: f32,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e1: Enum1,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e2: Enum2,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e3: Enum3,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e4: Enum4,
|
||||||
|
#[serde(flatten)]
|
||||||
|
e5: Enum5,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContainerDenyUnknownFields {
|
||||||
|
fn_values!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn json_with_extra_field() -> Value {
|
||||||
|
json!({
|
||||||
|
"f": 1.23,
|
||||||
|
"B": true,
|
||||||
|
"F": 4.56,
|
||||||
|
"S2": "abc",
|
||||||
|
"U2": 789,
|
||||||
|
"B3": false,
|
||||||
|
"extra": null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enums_flattened() {
|
||||||
|
test!(Container)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(Container::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_allows_de_roundtrip([json_with_extra_field()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enums_flattened_deny_unknown_fields() {
|
||||||
|
test!(ContainerDenyUnknownFields)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(ContainerDenyUnknownFields::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_rejects_de([json_with_extra_field()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn enums_flattened_deny_unknown_fields_draft07() {
|
||||||
|
test!(ContainerDenyUnknownFields, SchemaSettings::draft07())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip(ContainerDenyUnknownFields::values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values())
|
||||||
|
.assert_rejects_de([json_with_extra_field()]);
|
||||||
|
}
|
|
@ -1,7 +1,4 @@
|
||||||
mod util;
|
use crate::prelude::*;
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::Serialize;
|
|
||||||
use util::*;
|
|
||||||
|
|
||||||
#[derive(Default, JsonSchema, Serialize)]
|
#[derive(Default, JsonSchema, Serialize)]
|
||||||
#[schemars(example = "Struct::default", example = "null")]
|
#[schemars(example = "Struct::default", example = "null")]
|
||||||
|
@ -20,6 +17,6 @@ fn eight() -> i32 {
|
||||||
fn null() {}
|
fn null() {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn examples() -> TestResult {
|
fn examples() {
|
||||||
test_default_generated_schema::<Struct>("examples")
|
test!(Struct).assert_snapshot();
|
||||||
}
|
}
|
169
schemars/tests/integration/extend.rs
Normal file
169
schemars/tests/integration/extend.rs
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#![allow(clippy::approx_constant)]
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
static THREE: f64 = 3.0;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(extend("obj" = {"array": [null, ()]}))]
|
||||||
|
#[schemars(extend("3" = THREE), extend("pi" = THREE + 0.14))]
|
||||||
|
struct Struct {
|
||||||
|
#[schemars(extend("foo" = "bar"))]
|
||||||
|
value: Value,
|
||||||
|
#[schemars(extend("type" = ["number", "string"]))]
|
||||||
|
int: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extend_struct() {
|
||||||
|
test!(Struct).assert_snapshot().custom(|schema, _| {
|
||||||
|
assert_eq!(schema.get("obj"), Some(&json!({ "array": [null, null] })));
|
||||||
|
assert_eq!(schema.get("3"), Some(&json!(3.0)));
|
||||||
|
assert_eq!(schema.get("pi"), Some(&json!(3.14)));
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/properties/value"),
|
||||||
|
Some(&json!({ "foo": "bar" }))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/properties/int/type"),
|
||||||
|
Some(&json!(["number", "string"]))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(extend("obj" = {"array": [null, ()]}))]
|
||||||
|
#[schemars(extend("3" = THREE), extend("pi" = THREE + 0.14))]
|
||||||
|
struct TupleStruct(
|
||||||
|
#[schemars(extend("foo" = "bar"))] Value,
|
||||||
|
#[schemars(extend("type" = ["number", "string"]))] usize,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extend_tuple_struct() {
|
||||||
|
test!(TupleStruct).assert_snapshot().custom(|schema, _| {
|
||||||
|
assert_eq!(schema.get("obj"), Some(&json!({ "array": [null, null] })));
|
||||||
|
assert_eq!(schema.get("3"), Some(&json!(3.0)));
|
||||||
|
assert_eq!(schema.get("pi"), Some(&json!(3.14)));
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/prefixItems/0"),
|
||||||
|
Some(&json!({ "foo": "bar" }))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer("/prefixItems/1/type"),
|
||||||
|
Some(&json!(["number", "string"]))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(extend("foo" = "bar"))]
|
||||||
|
enum ExternalEnum {
|
||||||
|
#[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_externally_tagged_enum() {
|
||||||
|
test!(ExternalEnum).assert_snapshot().custom(|schema, _| {
|
||||||
|
assert_eq!(schema.get("foo"), Some(&json!("bar")));
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer(&format!("/oneOf/{i}/foo")),
|
||||||
|
Some(&json!("bar"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(tag = "t", extend("foo" = "bar"))]
|
||||||
|
enum InternalEnum {
|
||||||
|
#[schemars(extend("foo" = "bar"))]
|
||||||
|
Unit,
|
||||||
|
#[schemars(extend("foo" = "bar"))]
|
||||||
|
NewType(Value),
|
||||||
|
#[schemars(extend("foo" = "bar"))]
|
||||||
|
Struct { i: i32, b: bool },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extend_internally_tagged_enum() {
|
||||||
|
test!(InternalEnum).assert_snapshot().custom(|schema, _| {
|
||||||
|
assert_eq!(schema.get("foo"), Some(&json!("bar")));
|
||||||
|
|
||||||
|
for i in 0..3 {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer(&format!("/oneOf/{i}/foo")),
|
||||||
|
Some(&json!("bar"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(tag = "t", content = "c", extend("foo" = "bar"))]
|
||||||
|
enum AdjacentEnum {
|
||||||
|
#[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_adjacently_tagged_enum() {
|
||||||
|
test!(AdjacentEnum).assert_snapshot().custom(|schema, _| {
|
||||||
|
assert_eq!(schema.get("foo"), Some(&json!("bar")));
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer(&format!("/oneOf/{i}/foo")),
|
||||||
|
Some(&json!("bar"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(untagged, extend("foo" = "bar"))]
|
||||||
|
enum UntaggedEnum {
|
||||||
|
#[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_untagged_enum() {
|
||||||
|
test!(UntaggedEnum).assert_snapshot().custom(|schema, _| {
|
||||||
|
assert_eq!(schema.get("foo"), Some(&json!("bar")));
|
||||||
|
|
||||||
|
for i in 0..4 {
|
||||||
|
assert_eq!(
|
||||||
|
schema.as_value().pointer(&format!("/anyOf/{i}/foo")),
|
||||||
|
Some(&json!("bar"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
93
schemars/tests/integration/flatten.rs
Normal file
93
schemars/tests/integration/flatten.rs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct Flat {
|
||||||
|
f: f32,
|
||||||
|
b: bool,
|
||||||
|
#[serde(default, skip_serializing_if = "str::is_empty")]
|
||||||
|
s: String,
|
||||||
|
v: Vec<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
#[schemars(rename = "Flat")]
|
||||||
|
struct Deep1 {
|
||||||
|
f: f32,
|
||||||
|
#[serde(flatten)]
|
||||||
|
deep2: Deep2,
|
||||||
|
v: Vec<i32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct Deep2 {
|
||||||
|
b: bool,
|
||||||
|
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||||
|
deep3: Option<Deep3>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct Deep3 {
|
||||||
|
s: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flattened_struct() {
|
||||||
|
test!(Deep1)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_identical::<Flat>()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
Deep1::default(),
|
||||||
|
Deep1 {
|
||||||
|
f: 1.0,
|
||||||
|
deep2: Deep2 {
|
||||||
|
b: true,
|
||||||
|
deep3: Some(Deep3 {
|
||||||
|
s: "test".to_owned(),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
v: vec![123],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct FlattenValue {
|
||||||
|
flag: bool,
|
||||||
|
#[serde(flatten)]
|
||||||
|
value: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
#[schemars(rename = "FlattenValue")]
|
||||||
|
struct FlattenMap {
|
||||||
|
flag: bool,
|
||||||
|
#[serde(flatten)]
|
||||||
|
value: BTreeMap<String, Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flattened_value() {
|
||||||
|
test!(FlattenValue)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
FlattenValue {
|
||||||
|
flag: false,
|
||||||
|
value: Value::Null,
|
||||||
|
},
|
||||||
|
FlattenValue {
|
||||||
|
flag: true,
|
||||||
|
value: Value::Object(Default::default()),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn flattened_map() {
|
||||||
|
test!(FlattenMap)
|
||||||
|
.assert_identical::<FlattenValue>()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
84
schemars/tests/integration/from_value.rs
Normal file
84
schemars/tests/integration/from_value.rs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use schemars::generate::SchemaSettings;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default, Clone)]
|
||||||
|
#[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(JsonSchema, Deserialize, Serialize, Default, Clone)]
|
||||||
|
pub struct MyInnerStruct {
|
||||||
|
pub my_map: BTreeMap<String, f64>,
|
||||||
|
pub my_vec: Vec<f32>,
|
||||||
|
pub my_empty_map: BTreeMap<String, f64>,
|
||||||
|
pub my_empty_vec: Vec<f32>,
|
||||||
|
pub my_tuple: (char, u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Clone)]
|
||||||
|
pub enum MyEnum {
|
||||||
|
NewType(String),
|
||||||
|
Struct { floats: Vec<f32> },
|
||||||
|
}
|
||||||
|
|
||||||
|
fn struct_value() -> MyStruct {
|
||||||
|
MyStruct {
|
||||||
|
my_int: 123,
|
||||||
|
my_bool: true,
|
||||||
|
my_nullable_enum: None,
|
||||||
|
my_inner_struct: MyInnerStruct {
|
||||||
|
my_map: [("k".to_owned(), 1.23)].into_iter().collect(),
|
||||||
|
my_vec: vec![1.0, 2.0, 3.0],
|
||||||
|
my_empty_map: BTreeMap::new(),
|
||||||
|
my_empty_vec: Vec::new(),
|
||||||
|
my_tuple: ('💩', 42),
|
||||||
|
},
|
||||||
|
_skip: 123,
|
||||||
|
skip_if_none: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn custom_struct() {
|
||||||
|
let value = struct_value();
|
||||||
|
|
||||||
|
test!(value: value.clone())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([value, MyStruct::default()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn custom_struct_openapi3() {
|
||||||
|
let value = struct_value();
|
||||||
|
|
||||||
|
test!(value: value.clone(), SchemaSettings::openapi3())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([value, MyStruct::default()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn json_value() {
|
||||||
|
let value = json!({
|
||||||
|
"zero": 0,
|
||||||
|
"zeroPointZero": 0.0,
|
||||||
|
"bool": true,
|
||||||
|
"null": null,
|
||||||
|
"object": {
|
||||||
|
"strings": ["foo", "bar"],
|
||||||
|
"mixed": [1, true]
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
test!(value: value.clone())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([value]);
|
||||||
|
}
|
159
schemars/tests/integration/garde.rs
Normal file
159
schemars/tests/integration/garde.rs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use garde::Validate;
|
||||||
|
|
||||||
|
const ONE: usize = 1;
|
||||||
|
const HUNDRED: usize = 10;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Validate)]
|
||||||
|
pub struct GardeAttrStruct {
|
||||||
|
#[garde(range(min = 1.0, max = 100.0))]
|
||||||
|
min_max: f32,
|
||||||
|
#[garde(range(min = ONE as f32, max = HUNDRED as f32))]
|
||||||
|
min_max2: f32,
|
||||||
|
#[garde(pattern(r"^[Hh]ello"))]
|
||||||
|
regex_str: String,
|
||||||
|
#[garde(contains(concat!("sub","string...")))]
|
||||||
|
contains_str: String,
|
||||||
|
#[garde(email)]
|
||||||
|
email_address: String,
|
||||||
|
#[garde(url)]
|
||||||
|
homepage: String,
|
||||||
|
#[garde(length(min = ONE, max = HUNDRED))]
|
||||||
|
non_empty_str: String,
|
||||||
|
#[garde(length(equal = 2), inner(length(min = 1)))]
|
||||||
|
pair: Vec<String>,
|
||||||
|
#[garde(required)]
|
||||||
|
required_option: Option<bool>,
|
||||||
|
#[garde(required, dive)]
|
||||||
|
#[serde(flatten)]
|
||||||
|
required_flattened: Option<GardeAttrInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Validate)]
|
||||||
|
pub struct GardeAttrInner {
|
||||||
|
#[garde(range(min = -100, max = 100))]
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GardeAttrStruct {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
min_max: 1.0,
|
||||||
|
min_max2: 1.0,
|
||||||
|
regex_str: "Hello world".to_owned(),
|
||||||
|
contains_str: "Contains substring...".to_owned(),
|
||||||
|
email_address: "test@test.test".to_owned(),
|
||||||
|
homepage: "http://test.test".to_owned(),
|
||||||
|
non_empty_str: "test".to_owned(),
|
||||||
|
pair: vec!["a".to_owned(), "b".to_owned()],
|
||||||
|
required_option: Some(true),
|
||||||
|
required_flattened: Some(GardeAttrInner { x: 0 }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GardeAttrStruct {
|
||||||
|
pub fn invalid_values() -> impl IntoIterator<Item = Self> {
|
||||||
|
static MUTATORS: &[fn(&mut GardeAttrStruct)] = &[
|
||||||
|
|v| v.min_max = 0.9,
|
||||||
|
|v| v.min_max = 100.1,
|
||||||
|
|v| v.min_max2 = 0.9,
|
||||||
|
|v| v.min_max2 = 100.1,
|
||||||
|
|v| v.regex_str = "fail".to_owned(),
|
||||||
|
|v| v.contains_str = "fail".to_owned(),
|
||||||
|
|v| v.email_address = "fail".to_owned(),
|
||||||
|
|v| v.homepage = "fail".to_owned(),
|
||||||
|
|v| v.non_empty_str = String::new(),
|
||||||
|
|v| v.pair = Vec::new(),
|
||||||
|
|v| v.pair = vec!["a".to_owned(), "b".to_owned(), "c".to_owned()],
|
||||||
|
|v| v.pair = vec!["".to_owned(), "b".to_owned()],
|
||||||
|
|v| v.required_option = None,
|
||||||
|
|v| v.required_flattened = None,
|
||||||
|
|v| v.required_flattened = Some(GardeAttrInner { x: -101 }),
|
||||||
|
|v| v.required_flattened = Some(GardeAttrInner { x: 101 }),
|
||||||
|
];
|
||||||
|
MUTATORS.iter().map(|f| {
|
||||||
|
let mut result = GardeAttrStruct::default();
|
||||||
|
f(&mut result);
|
||||||
|
result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn garde_attrs() {
|
||||||
|
test!(GardeAttrStruct)
|
||||||
|
.with_validator(|v| v.validate().is_ok())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_rejects_invalid(GardeAttrStruct::invalid_values())
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
#[schemars(rename = "GardeAttrStruct")]
|
||||||
|
pub struct SchemarsAttrStruct {
|
||||||
|
#[schemars(range(min = 1.0, max = 100.0))]
|
||||||
|
min_max: f32,
|
||||||
|
#[schemars(range(min = ONE as f32, max = HUNDRED as f32))]
|
||||||
|
min_max2: f32,
|
||||||
|
#[schemars(pattern(r"^[Hh]ello"))]
|
||||||
|
regex_str: String,
|
||||||
|
#[schemars(contains(concat!("sub","string...")))]
|
||||||
|
contains_str: String,
|
||||||
|
#[schemars(email)]
|
||||||
|
email_address: String,
|
||||||
|
#[schemars(url)]
|
||||||
|
homepage: String,
|
||||||
|
#[schemars(length(min = ONE, max = HUNDRED))]
|
||||||
|
non_empty_str: String,
|
||||||
|
#[schemars(length(equal = 2), inner(length(min = 1)))]
|
||||||
|
pair: Vec<String>,
|
||||||
|
#[schemars(required)]
|
||||||
|
required_option: Option<bool>,
|
||||||
|
#[schemars(required)]
|
||||||
|
#[serde(flatten)]
|
||||||
|
required_flattened: Option<SchemarsAttrInner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
#[derive(JsonSchema)]
|
||||||
|
pub struct SchemarsAttrInner {
|
||||||
|
#[schemars(range(min = -100, max = 100))]
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn schemars_attrs() {
|
||||||
|
test!(SchemarsAttrStruct).assert_identical::<GardeAttrStruct>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Validate)]
|
||||||
|
pub struct GardeAttrTuple(
|
||||||
|
#[garde(range(max = 10))] u8,
|
||||||
|
#[garde(required)] Option<bool>,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn garde_attrs_tuple() {
|
||||||
|
test!(GardeAttrTuple)
|
||||||
|
.with_validator(|v| v.validate().is_ok())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([GardeAttrTuple(10, Some(false))])
|
||||||
|
.assert_rejects_invalid([GardeAttrTuple(11, Some(false)), GardeAttrTuple(10, None)])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Validate)]
|
||||||
|
pub struct GardeAttrNewType(#[garde(range(max = 10))] u8);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn garde_attrs_newtype() {
|
||||||
|
test!(GardeAttrNewType)
|
||||||
|
.with_validator(|v| v.validate().is_ok())
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([GardeAttrNewType(10)])
|
||||||
|
.assert_rejects_invalid([GardeAttrNewType(11)])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
19
schemars/tests/integration/indexmap.rs
Normal file
19
schemars/tests/integration/indexmap.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use indexmap2::{indexmap, indexset, IndexMap, IndexSet};
|
||||||
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn indexmap() {
|
||||||
|
test!(IndexMap<String, bool>)
|
||||||
|
.assert_identical::<BTreeMap<String, bool>>()
|
||||||
|
.assert_allows_ser_roundtrip([indexmap!(), indexmap!("key".to_owned() => true)])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn indexset() {
|
||||||
|
test!(IndexSet<String>)
|
||||||
|
.assert_identical::<BTreeSet<String>>()
|
||||||
|
.assert_allows_ser_roundtrip([indexset!(), indexset!("test".to_owned())])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
61
schemars/tests/integration/inline_subschemas.rs
Normal file
61
schemars/tests/integration/inline_subschemas.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
use schemars::generate::SchemaSettings;
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct MyJob {
|
||||||
|
spec: MyJobSpec,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize, Default)]
|
||||||
|
struct MyJobSpec {
|
||||||
|
replicas: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_normal() {
|
||||||
|
let settings = SchemaSettings::default().with(|s| s.inline_subschemas = true);
|
||||||
|
test!(MyJob, settings)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip_default()
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct RecursiveOuter {
|
||||||
|
direct: Option<Box<RecursiveOuter>>,
|
||||||
|
indirect: Option<Box<RecursiveInner>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(JsonSchema, Deserialize, Serialize)]
|
||||||
|
struct RecursiveInner {
|
||||||
|
recursive: RecursiveOuter,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn struct_recursive() {
|
||||||
|
let settings = SchemaSettings::default().with(|s| s.inline_subschemas = true);
|
||||||
|
test!(RecursiveOuter, settings)
|
||||||
|
.assert_snapshot()
|
||||||
|
.assert_allows_ser_roundtrip([
|
||||||
|
RecursiveOuter {
|
||||||
|
direct: None,
|
||||||
|
indirect: None,
|
||||||
|
},
|
||||||
|
RecursiveOuter {
|
||||||
|
direct: Some(Box::new(RecursiveOuter {
|
||||||
|
direct: None,
|
||||||
|
indirect: None,
|
||||||
|
})),
|
||||||
|
indirect: Some(Box::new(RecursiveInner {
|
||||||
|
recursive: RecursiveOuter {
|
||||||
|
direct: Some(Box::new(RecursiveOuter {
|
||||||
|
direct: None,
|
||||||
|
indirect: None,
|
||||||
|
})),
|
||||||
|
indirect: None,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.assert_matches_de_roundtrip(arbitrary_values());
|
||||||
|
}
|
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