Compare commits

..

No commits in common. "f8c1fe21b72a367a4814530e1b1a1f3693e86088" and "0a7aa5ebf0392abe183ee2d0ab1adb452b3d8b13" have entirely different histories.

255 changed files with 4979 additions and 6018 deletions

View file

@ -8,12 +8,12 @@ jobs:
strategy:
matrix:
rust:
- 1.70.0
- 1.65.0
- stable
- beta
- nightly
include:
- rust: 1.70.0
- rust: 1.65.0
allow_failure: false
- rust: stable
allow_failure: false
@ -23,10 +23,12 @@ jobs:
allow_failure: true
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
- uses: actions/checkout@v1
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- name: Check with no feature flags
run: cargo check --verbose --no-default-features
continue-on-error: ${{ matrix.allow_failure }}

View file

@ -1,27 +1,5 @@
# Changelog
## [1.0.0-alpha.17] - 2024-12-02
### Changed
- For newtype variants of internally-tagged enums, prefer referencing the inner type's schema via `$ref` instead of always inlining the schema (https://github.com/GREsau/schemars/pull/355) _(this change was included in the release notes for 1.0.0-alpha.16, but was accidentally excluded from the published crate)_
## [1.0.0-alpha.16] - 2024-11-25
### Removed (_⚠ breaking changes ⚠_)
- the `enumset1`/`enumset` optional dependency has been removed, as its `JsonSchema` impl did not actually match the default serialization format of `EnumSet` (https://github.com/GREsau/schemars/pull/339)
### Changed (_⚠ breaking changes ⚠_)
- MSRV is now 1.70
- [The `example` attribute](https://graham.cool/schemars/deriving/attributes/#example) value is now an arbitrary expression, rather than a string literal identifying a function to call. To avoid silent behaviour changes, the expression must not be a string literal where the value can be parsed as a function path - e.g. `#[schemars(example = "foo")]` is now a compile error, but `#[schemars(example = foo())]` is allowed (as is `#[schemars(example = &"foo")]` if you want the the literal string value `"foo"` to be the example).
### Fixed
- The "deserialize" schema for `bytes::Bytes`/`BytesMut` now allows strings, matching the actual deserialize behaviour of the types.
- The schema for `either::Either` now matches the actual serialize/deserialize behaviour of that type.
## [1.0.0-alpha.15] - 2024-09-05
### Added

1108
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@
[![CI Build](https://img.shields.io/github/actions/workflow/status/GREsau/schemars/ci.yml?branch=master&logo=GitHub)](https://github.com/GREsau/schemars/actions)
[![Crates.io](https://img.shields.io/crates/v/schemars)](https://crates.io/crates/schemars)
[![Docs](https://img.shields.io/docsrs/schemars/1.0.0--latest?label=docs)](https://docs.rs/schemars/1.0.0--latest)
[![MSRV 1.70+](https://img.shields.io/badge/msrv-1.70-blue)](https://blog.rust-lang.org/2023/06/01/Rust-1.70.0.html)
[![MSRV 1.65+](https://img.shields.io/badge/msrv-1.65-blue)](https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html)
Generate JSON Schema documents from Rust code
@ -268,6 +268,7 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
- `bytes1` - [bytes](https://crates.io/crates/bytes) (^1.0)
- `chrono04` - [chrono](https://crates.io/crates/chrono) (^0.4)
- `either1` - [either](https://crates.io/crates/either) (^1.3)
- `enumset1` - [enumset](https://crates.io/crates/enumset) (^1.0)
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
- `rust_decimal1` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
- `semver1` - [semver](https://crates.io/crates/semver) (^1.0.9)
@ -280,5 +281,5 @@ For example, to implement `JsonSchema` on types from `chrono`, enable it as a fe
```toml
[dependencies]
schemars = { version = "1.0.0-alpha.17", features = ["chrono04"] }
schemars = { version = "1.0.0-alpha.15", features = ["chrono04"] }
```

View file

@ -23,9 +23,10 @@ All optional dependencies are now suffixed by their version:
- `url` is now `url2`
- `bytes` is now `bytes1`
- `rust_decimal` is now `rust_decimal1`
- `enumset` is now `enumset1`
- `smol_str` is now `smol_str02`
- `semver` is now `semver1`
- `enumset`, `indexmap`, `uuid08`, `arrayvec05` and `bigdecimal03` have been removed
- `indexmap`, `uuid08`, `arrayvec05` and `bigdecimal03` have been removed
- `indexmap2`, `arrayvec07` and `bigdecimal04` are unchanged
## `Schema` is now a wrapper around `serde_json::Value`

View file

@ -18,6 +18,7 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
- `bytes1` - [bytes](https://crates.io/crates/bytes) (^1.0)
- `chrono04` - [chrono](https://crates.io/crates/chrono) (^0.4)
- `either1` - [either](https://crates.io/crates/either) (^1.3)
- `enumset1` - [enumset](https://crates.io/crates/enumset) (^1.0)
- `indexmap2` - [indexmap](https://crates.io/crates/indexmap) (^2.0)
- `rust_decimal1` - [rust_decimal](https://crates.io/crates/rust_decimal) (^1.0)
- `semver1` - [semver](https://crates.io/crates/semver) (^1.0.9)
@ -30,5 +31,5 @@ For example, to implement `JsonSchema` on types from `chrono`, enable it as a fe
```toml
[dependencies]
schemars = { version = "1.0.0-alpha.17", features = ["chrono04"] }
schemars = { version = "1.0.0-alpha.15", features = ["chrono04"] }
```

View file

@ -298,15 +298,13 @@ Set on a container, variant or field to set the generated schema's `title` and/o
<h3 id="example">
`#[schemars(example = value)]`
`#[schemars(example = "some::function")]`
</h3>
Set on a container, variant or field to include the given value in the generated schema's `examples`. The value can be any type that implements serde's `Serialize` trait - it does not need to be the same type as the attached struct/field. This attribute can be repeated to specify multiple examples.
Set on a container, variant or field to include the result of the given function in the generated schema's `examples`. The function should take no parameters and can return any type that implements serde's `Serialize` trait - it does not need to return the same type as the attached struct/field. This attribute can be repeated to specify multiple examples.
In previous versions of schemars, the value had to be a string literal identifying a defined function that would be called to return the actual example value (similar to the [`default`](#default) attribute). To avoid the new attribute behaviour from silently breaking old consumers, string literals consisting of a single word (e.g. `#[schemars(example = "my_fn")]`) or a path (e.g. `#[schemars(example = "my_mod::my_fn")]`) are currently disallowed. This restriction may be relaxed in a future version of schemars, but for now if you want to include such a string as the literal example value, this can be done by borrowing the value, e.g. `#[schemars(example = &"my_fn")]`. If you instead want to call a function to get the example value (mirrorring the old behaviour), you must use an explicit function call expression, e.g. `#[schemars(example = my_fn())]`.
Alternatively, to directly set multiple examples without repeating `example = ...` attribute, you can instead use the [`extend`](#extend) attribute, e.g. `#[schemars(extend("examples" = [1, 2, 3]))]`.
To use the result of arbitrary expressions as examples, you can instead use the [`extend`](#extend) attribute, e.g. `[schemars(extend("examples" = ["example string"]))]`.
<h3 id="deprecated">

View file

@ -3,17 +3,17 @@ name = "schemars"
description = "Generate JSON Schemas from Rust code"
homepage = "https://graham.cool/schemars/"
repository = "https://github.com/GREsau/schemars"
version = "1.0.0-alpha.17"
version = "1.0.0-alpha.15"
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
edition = "2021"
license = "MIT"
readme = "README.md"
keywords = ["rust", "json-schema", "serde"]
categories = ["encoding", "no-std"]
rust-version = "1.70"
rust-version = "1.65"
[dependencies]
schemars_derive = { version = "=1.0.0-alpha.17", optional = true, path = "../schemars_derive" }
schemars_derive = { version = "=1.0.0-alpha.15", optional = true, path = "../schemars_derive" }
serde = { version = "1.0", default-features = false, features = ["alloc"]}
serde_json = { version = "1.0.127", default-features = false, features = ["alloc"] }
dyn-clone = "1.0"
@ -24,9 +24,10 @@ arrayvec07 = { version = "0.7", default-features = false, optional = true, packa
bigdecimal04 = { version = "0.4", default-features = false, optional = true, package = "bigdecimal" }
bytes1 = { version = "1.0", default-features = false, optional = true, package = "bytes" }
chrono04 = { version = "0.4", default-features = false, optional = true, package = "chrono" }
either1 = { version = "1.3", default-features = false, optional = true, package = "either" }
either1 = { version = "1.3", default-features = false, optional = true, package = "either" }
enumset1 = { version = "1.0", default-features = false, optional = true, package = "enumset" }
indexmap2 = { version = "2.0", default-features = false, optional = true, package = "indexmap" }
rust_decimal1 = { version = "1", default-features = false, optional = true, package = "rust_decimal" }
rust_decimal1 = { version = "1", default-features = false, optional = true, package = "rust_decimal"}
semver1 = { version = "1.0.9", default-features = false, optional = true, package = "semver" }
smallvec1 = { version = "1.0", default-features = false, optional = true, package = "smallvec" }
smol_str02 = { version = "0.2.1", default-features = false, optional = true, package = "smol_str" }
@ -37,26 +38,6 @@ uuid1 = { version = "1.0", default-features = false, optional = true, package =
pretty_assertions = "1.2.1"
trybuild = "1.0"
serde = { version = "1.0", features = ["derive"] }
jsonschema = { version = "0.20", default-features = false }
snapbox = { version = "0.6.17", features = ["json"] }
serde_repr = "0.1.19"
# Use github source until published garde version supports `length(equal = ...)` attr
garde = { git = "https://github.com/jprochazk/garde.git", rev = "be00ddddf8de14530ee890ccfdbaf0b13fb32852", features = ["derive", "email", "regex", "url"] }
validator = { version = "0.18.1", features = ["derive"] }
regex = { version = "1.10.6", default-features = false }
arrayvec07 = { version = "0.7", default-features = false, features = ["serde"], package = "arrayvec"}
bigdecimal04 = { version = "0.4", default-features = false, features = ["serde"], package = "bigdecimal" }
bytes1 = { version = "1.0", default-features = false, features = ["serde"], package = "bytes" }
chrono04 = { version = "0.4", default-features = false, features = ["serde"], package = "chrono" }
either1 = { version = "1.3", default-features = false, features = ["serde"], package = "either" }
indexmap2 = { version = "2.0", default-features = false, features = ["serde"], package = "indexmap" }
rust_decimal1 = { version = "1", default-features = false, features = ["serde"], package = "rust_decimal" }
semver1 = { version = "1.0.9", default-features = false, features = ["serde"], package = "semver" }
smallvec1 = { version = "1.0", default-features = false, features = ["serde"], package = "smallvec" }
smol_str02 = { version = "0.2.1", default-features = false, features = ["serde"], package = "smol_str" }
url2 = { version = "2.0", default-features = false, features = ["serde"], package = "url" }
uuid1 = { version = "1.0", default-features = false, features = ["serde"], package = "uuid" }
[features]
default = ["derive", "std"]
@ -79,10 +60,66 @@ raw_value = ["serde_json/raw_value"]
# For internal/CI use only
_ui_test = []
[[test]]
name = "std_time"
required-features = ["std"]
[[test]]
name = "ffi"
required-features = ["std"]
[[test]]
name = "ui"
required-features = ["_ui_test"]
[[test]]
name = "chrono"
required-features = ["chrono04"]
[[test]]
name = "indexmap"
required-features = ["indexmap2"]
[[test]]
name = "either"
required-features = ["either1"]
[[test]]
name = "uuid"
required-features = ["uuid1"]
[[test]]
name = "smallvec"
required-features = ["smallvec1"]
[[test]]
name = "bytes"
required-features = ["bytes1"]
[[test]]
name = "arrayvec"
required-features = ["arrayvec07"]
[[test]]
name = "url"
required-features = ["url2"]
[[test]]
name = "enumset"
required-features = ["enumset1"]
[[test]]
name = "smol_str"
required-features = ["smol_str02"]
[[test]]
name = "semver"
required-features = ["semver1"]
[[test]]
name = "decimal"
required-features = ["rust_decimal1", "bigdecimal04"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--extend-css", "docs-rs-custom.css"]

View file

@ -1,5 +1,5 @@
use crate::_alloc_prelude::*;
use crate::transform::{transform_immediate_subschemas, Transform};
use crate::transform::transform_immediate_subschemas;
use crate::{JsonSchema, Schema, SchemaGenerator};
use serde::Serialize;
use serde_json::{json, map::Entry, Map, Value};
@ -12,39 +12,6 @@ pub extern crate serde_json;
pub use rustdoc::get_title_and_description;
pub fn json_schema_for_internally_tagged_enum_newtype_variant<T: ?Sized + JsonSchema>(
generator: &mut SchemaGenerator,
) -> Schema {
let mut schema = T::json_schema(generator);
// Inline the newtype's inner schema if any of:
// - The type specifies that its schema should always be inlined
// - The generator settings specify that all schemas should be inlined
// - The inner type is a unit struct, which would cause an unsatisfiable schema due to mismatched `type`.
// In this case, we replace its type with "object" in `apply_internal_enum_variant_tag`
// - The inner schema specified `"additionalProperties": false` or `"unevaluatedProperties": false`,
// since that would disallow the variant tag. If additional/unevaluatedProperties is in the top-level
// schema, then we can leave it there, because it will "see" the variant tag property. But if it is
// nested e.g. in an `allOf`, then it must be removed, which is why we run `AllowUnknownProperties`
// but only on immediate subschemas.
let mut transform = AllowUnknownProperties::default();
transform_immediate_subschemas(&mut transform, &mut schema);
if T::always_inline_schema()
|| generator.settings().inline_subschemas
|| schema.get("type").and_then(Value::as_str) == Some("null")
|| schema.get("additionalProperties").and_then(Value::as_bool) == Some(false)
|| schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false)
|| transform.did_modify
{
return schema;
}
// ...otherwise, we can freely refer to the schema via a `$ref`
generator.subschema_for::<T>()
}
// Helper for generating schemas for flattened `Option` fields.
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
generator: &mut SchemaGenerator,
@ -58,29 +25,20 @@ pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
// Always allow aditional/unevaluated properties, because the outer struct determines
// whether it denies unknown fields.
AllowUnknownProperties::default().transform(&mut schema);
allow_unknown_properties(&mut schema);
schema
}
#[derive(Default)]
struct AllowUnknownProperties {
did_modify: bool,
}
impl Transform for AllowUnknownProperties {
fn transform(&mut self, schema: &mut Schema) {
if schema.get("additionalProperties").and_then(Value::as_bool) == Some(false) {
schema.remove("additionalProperties");
self.did_modify = true;
}
if schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false) {
schema.remove("unevaluatedProperties");
self.did_modify = true;
}
transform_immediate_subschemas(self, schema);
fn allow_unknown_properties(schema: &mut Schema) {
if schema.get("additionalProperties").and_then(Value::as_bool) == Some(false) {
schema.remove("additionalProperties");
}
if schema.get("unevaluatedProperties").and_then(Value::as_bool) == Some(false) {
schema.remove("unevaluatedProperties");
}
transform_immediate_subschemas(&mut allow_unknown_properties, schema);
}
/// Hack to simulate specialization:

View file

@ -671,14 +671,13 @@ where
impl Debug for Box<dyn GenTransform> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
#[allow(clippy::used_underscore_items)]
self._debug_type_name(f)
}
}
fn _assert_send() {
fn assert<T: Send>() {}
fn _assert<T: Send>() {}
assert::<SchemaSettings>();
assert::<SchemaGenerator>();
_assert::<SchemaSettings>();
_assert::<SchemaGenerator>();
}

View file

@ -1,29 +0,0 @@
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);

View file

@ -58,5 +58,5 @@ macro_rules! formatted_string_impl {
formatted_string_impl!(NaiveDate, "date");
formatted_string_impl!(NaiveDateTime, "partial-date-time");
formatted_string_impl!(NaiveTime, "partial-time");
formatted_string_impl!(NaiveTime, "partial-date-time");
formatted_string_impl!(DateTime, "date-time", <Tz: TimeZone> JsonSchema for DateTime<Tz>);

View file

@ -17,28 +17,7 @@ impl<L: JsonSchema, R: JsonSchema> JsonSchema for Either<L, R> {
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
json_schema!({
"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"
]
}
]
"anyOf": [generator.subschema_for::<L>(), generator.subschema_for::<R>()],
})
}
}

View file

@ -2,7 +2,6 @@ use crate::SchemaGenerator;
use crate::_alloc_prelude::*;
use crate::{json_schema, JsonSchema, Schema};
use alloc::borrow::Cow;
use serde_json::json;
use std::ffi::{CStr, CString, OsStr, OsString};
impl JsonSchema for OsString {
@ -38,31 +37,5 @@ impl JsonSchema for OsString {
forward_impl!(OsStr => OsString);
impl JsonSchema for CString {
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);
forward_impl!(CString => Vec<u8>);
forward_impl!(CStr => Vec<u8>);

View file

@ -42,7 +42,8 @@ macro_rules! forward_impl {
mod array;
mod core;
mod maps;
mod nonzero;
mod nonzero_signed;
mod nonzero_unsigned;
mod primitives;
mod sequences;
mod serdejson;
@ -60,7 +61,10 @@ mod ffi;
mod arrayvec07;
#[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")]
mod chrono04;
@ -71,6 +75,9 @@ mod decimal;
#[cfg(feature = "either1")]
mod either1;
#[cfg(feature = "enumset1")]
forward_impl!((<T: enumset1::EnumSetType + crate::JsonSchema> crate::JsonSchema for enumset1::EnumSet<T>) => alloc::collections::BTreeSet<T>);
#[cfg(feature = "indexmap2")]
mod indexmap2;

View file

@ -1,64 +0,0 @@
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);

View file

@ -0,0 +1,37 @@
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);

View file

@ -0,0 +1,36 @@
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);

View file

@ -4,8 +4,10 @@ use alloc::borrow::Cow;
use semver1::Version;
impl JsonSchema for Version {
always_inline!();
fn schema_name() -> Cow<'static, str> {
"SemVer".into()
"Version".into()
}
fn schema_id() -> Cow<'static, str> {

View file

@ -145,6 +145,7 @@ pub mod r#gen {
///
/// assert_eq!(<GenericType<i32>>::schema_id(), <&mut GenericType<&i32>>::schema_id());
/// ```
pub trait JsonSchema {
/// Whether JSON Schemas generated for this type should be included directly in parent schemas,
/// rather than being re-used where possible using the `$ref` keyword.

View file

@ -0,0 +1,3 @@
# 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.

View file

@ -0,0 +1,12 @@
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")
}

View file

@ -1,6 +1,9 @@
use crate::prelude::*;
mod util;
use std::marker::PhantomData;
use schemars::JsonSchema;
use util::*;
struct MyIterator;
impl Iterator for MyIterator {
@ -13,7 +16,7 @@ impl Iterator for MyIterator {
// The default trait bounds would require T to implement JsonSchema,
// which MyIterator does not.
#[derive(JsonSchema, Serialize, Deserialize)]
#[derive(JsonSchema)]
#[schemars(bound = "T::Item: JsonSchema", rename = "MyContainer")]
pub struct MyContainer<T>
where
@ -24,12 +27,6 @@ where
}
#[test]
fn manual_bound_set() {
test!(MyContainer<MyIterator>)
.assert_snapshot()
.assert_allows_ser_roundtrip([MyContainer {
associated: "test".to_owned(),
generic: PhantomData,
}])
.assert_matches_de_roundtrip(arbitrary_values());
fn manual_bound_set() -> TestResult {
test_default_generated_schema::<MyContainer<MyIterator>>("bound")
}

8
schemars/tests/bytes.rs Normal file
View file

@ -0,0 +1,8 @@
mod util;
use bytes1::{Bytes, BytesMut};
use util::*;
#[test]
fn bytes() -> TestResult {
test_default_generated_schema::<(Bytes, BytesMut)>("bytes")
}

19
schemars/tests/chrono.rs Normal file
View file

@ -0,0 +1,19 @@
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")
}

214
schemars/tests/contract.rs Normal file
View file

@ -0,0 +1,214 @@
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(),
)
}

View file

@ -0,0 +1,20 @@
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")
}

12
schemars/tests/decimal.rs Normal file
View file

@ -0,0 +1,12 @@
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")
}

59
schemars/tests/default.rs Normal file
View file

@ -0,0 +1,59 @@
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")
}

View file

@ -0,0 +1,39 @@
#![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")
}

View file

@ -1,4 +1,6 @@
use crate::prelude::*;
mod util;
use schemars::JsonSchema;
use util::*;
#[allow(dead_code)]
#[derive(JsonSchema)]
@ -22,11 +24,6 @@ struct MyStruct {
#[derive(JsonSchema)]
struct MyUnitStruct;
#[test]
fn doc_comments_struct() {
test!(MyStruct).assert_snapshot();
}
#[allow(dead_code)]
#[doc = " # This is the enum's title "]
#[doc = " This is "]
@ -58,8 +55,13 @@ enum MyEnum {
}
#[test]
fn doc_comments_enum() {
test!(MyEnum).assert_snapshot();
fn doc_comments_struct() -> TestResult {
test_default_generated_schema::<MyStruct>("doc_comments_struct")
}
#[test]
fn doc_comments_enum() -> TestResult {
test_default_generated_schema::<MyEnum>("doc_comments_enum")
}
/// # OverrideDocs struct
@ -80,6 +82,6 @@ struct OverrideDocs {
}
#[test]
fn doc_comments_override() {
test!(OverrideDocs).assert_snapshot();
fn doc_comments_override() -> TestResult {
test_default_generated_schema::<OverrideDocs>("doc_comments_override")
}

8
schemars/tests/either.rs Normal file
View file

@ -0,0 +1,8 @@
mod util;
use either1::Either;
use util::*;
#[test]
fn either() -> TestResult {
test_default_generated_schema::<Either<i32, Either<bool, ()>>>("either")
}

185
schemars/tests/enum.rs Normal file
View file

@ -0,0 +1,185 @@
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")
}

View file

@ -0,0 +1,127 @@
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")
}

View file

@ -0,0 +1,89 @@
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(),
)
}

View file

@ -0,0 +1,35 @@
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")
}

18
schemars/tests/enumset.rs Normal file
View file

@ -0,0 +1,18 @@
mod util;
use enumset1::{EnumSet, EnumSetType};
use schemars::JsonSchema;
use util::*;
// needed to derive EnumSetType when using a crate alias
extern crate enumset1 as enumset;
#[derive(EnumSetType, JsonSchema)]
enum Foo {
Bar,
Baz,
}
#[test]
fn enumset() -> TestResult {
test_default_generated_schema::<EnumSet<Foo>>("enumset")
}

View file

@ -0,0 +1,25 @@
mod util;
use schemars::JsonSchema;
use serde::Serialize;
use util::*;
#[derive(Default, JsonSchema, Serialize)]
#[schemars(example = "Struct::default", example = "null")]
struct Struct {
#[schemars(example = "eight", example = "null")]
foo: i32,
bar: bool,
#[schemars(example = "null")]
baz: Option<&'static str>,
}
fn eight() -> i32 {
8
}
fn null() {}
#[test]
fn examples() -> TestResult {
test_default_generated_schema::<Struct>("examples")
}

View file

@ -1,10 +1,10 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Array_up_to_size_8_of_int32",
"title": "Array_up_to_size_16_of_int32",
"type": "array",
"items": {
"type": "integer",
"format": "int32"
},
"maxItems": 8
"maxItems": 16
}

View file

@ -1,5 +1,5 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "NewType",
"title": "string",
"type": "string"
}

View file

@ -0,0 +1,25 @@
{
"$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
}

View file

@ -29,7 +29,7 @@
},
"naive_time": {
"type": "string",
"format": "partial-time"
"format": "partial-date-time"
}
},
"required": [

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "StructAllowUnknownFields",
"title": "MyStruct",
"type": "object",
"properties": {
"write_only": {

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "StructAllowUnknownFields",
"title": "MyStruct",
"type": "object",
"properties": {
"READ-ONLY": {

View file

@ -1,10 +1,12 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "NormalStruct",
"title": "Struct",
"type": "object",
"properties": {
"foo": {
"type": "string"
"description": "This is a document",
"type": "integer",
"format": "int32"
},
"bar": {
"type": "boolean"

View file

@ -0,0 +1,52 @@
{
"$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"
}
}
}

View file

@ -7,14 +7,14 @@
"type": "integer",
"format": "int32"
},
"bar": {
"deprecated_field": {
"type": "boolean",
"deprecated": true
}
},
"required": [
"foo",
"bar"
"deprecated_field"
],
"deprecated": true
}

View file

@ -0,0 +1,57 @@
{
"$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"
]
}
}
}

View file

@ -0,0 +1,20 @@
{
"$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"
}
]
}
]
}

View file

@ -5,24 +5,24 @@
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "Unit"
"const": "UnitOne"
}
},
"required": [
"tag"
"t"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "StringMap"
},
"content": {
"c": {
"type": "object",
"additionalProperties": {
"type": "string"
@ -30,53 +30,53 @@
}
},
"required": [
"tag",
"content"
"t",
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "UnitStructNewType"
},
"c": {
"$ref": "#/$defs/UnitStruct"
}
},
"required": [
"t",
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"t": {
"type": "string",
"const": "StructNewType"
},
"content": {
"c": {
"$ref": "#/$defs/Struct"
}
},
"required": [
"tag",
"content"
"t",
"c"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tag": {
"type": "string",
"const": "StructDenyUnknownFieldsNewType"
},
"content": {
"$ref": "#/$defs/StructDenyUnknownFields"
}
},
"required": [
"tag",
"content"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "Struct"
},
"content": {
"c": {
"type": "object",
"properties": {
"foo": {
@ -95,13 +95,75 @@
}
},
"required": [
"tag",
"content"
"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": {
@ -117,23 +179,6 @@
"foo",
"bar"
]
},
"StructDenyUnknownFields": {
"type": "object",
"properties": {
"baz": {
"type": "integer",
"format": "int32"
},
"foobar": {
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"baz",
"foobar"
]
}
}
}

View file

@ -5,23 +5,23 @@
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "UnitOne"
}
},
"required": [
"tag"
"t"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "StringMap"
},
"content": {
"c": {
"type": "object",
"additionalProperties": {
"type": "string"
@ -29,50 +29,50 @@
}
},
"required": [
"tag",
"content"
"t",
"c"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "UnitStructNewType"
},
"content": {
"c": {
"$ref": "#/$defs/UnitStruct"
}
},
"required": [
"tag",
"content"
"t",
"c"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "StructNewType"
},
"content": {
"c": {
"$ref": "#/$defs/Struct"
}
},
"required": [
"tag",
"content"
"t",
"c"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "Struct"
},
"content": {
"c": {
"type": "object",
"properties": {
"foo": {
@ -90,18 +90,18 @@
}
},
"required": [
"tag",
"content"
"t",
"c"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "Tuple"
},
"content": {
"c": {
"type": "array",
"prefixItems": [
{
@ -117,55 +117,37 @@
}
},
"required": [
"tag",
"content"
"t",
"c"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "UnitTwo"
}
},
"required": [
"tag"
"t"
]
},
{
"type": "object",
"properties": {
"tag": {
"t": {
"type": "string",
"const": "UnitAsInt"
"const": "WithInt"
},
"content": {
"c": {
"type": "integer",
"format": "uint64",
"minimum": 0
"format": "int32"
}
},
"required": [
"tag",
"content"
]
},
{
"type": "object",
"properties": {
"tag": {
"type": "string",
"const": "TupleAsStr"
},
"content": {
"type": "string",
"pattern": "^\\d+ (true|false)$"
}
},
"required": [
"tag",
"content"
"t",
"c"
]
}
],

View file

@ -62,6 +62,7 @@
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"foo",
"bar"
@ -99,27 +100,13 @@
{
"type": "object",
"properties": {
"unitAsInt": {
"withInt": {
"type": "integer",
"format": "uint64",
"minimum": 0
"format": "int32"
}
},
"required": [
"unitAsInt"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tupleAsStr": {
"type": "string",
"pattern": "^\\d+ (true|false)$"
}
},
"required": [
"tupleAsStr"
"withInt"
],
"additionalProperties": false
}

View file

@ -5,13 +5,14 @@
{
"type": "string",
"enum": [
"Unit"
"unitOne",
"unitTwo"
]
},
{
"type": "object",
"properties": {
"StringMap": {
"stringMap": {
"type": "object",
"additionalProperties": {
"type": "string"
@ -19,38 +20,38 @@
}
},
"required": [
"StringMap"
"stringMap"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"StructNewType": {
"unitStructNewType": {
"$ref": "#/$defs/UnitStruct"
}
},
"required": [
"unitStructNewType"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"structNewType": {
"$ref": "#/$defs/Struct"
}
},
"required": [
"StructNewType"
"structNewType"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"StructDenyUnknownFieldsNewType": {
"$ref": "#/$defs/StructDenyUnknownFields"
}
},
"required": [
"StructDenyUnknownFieldsNewType"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"Struct": {
"struct": {
"type": "object",
"properties": {
"foo": {
@ -61,7 +62,6 @@
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"foo",
"bar"
@ -69,12 +69,51 @@
}
},
"required": [
"Struct"
"struct"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tuple": {
"type": "array",
"prefixItems": [
{
"type": "integer",
"format": "int32"
},
{
"type": "boolean"
}
],
"minItems": 2,
"maxItems": 2
}
},
"required": [
"tuple"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"withInt": {
"type": "integer",
"format": "int32"
}
},
"required": [
"withInt"
],
"additionalProperties": false
}
],
"$defs": {
"UnitStruct": {
"type": "null"
},
"Struct": {
"type": "object",
"properties": {
@ -90,23 +129,6 @@
"foo",
"bar"
]
},
"StructDenyUnknownFields": {
"type": "object",
"properties": {
"baz": {
"type": "integer",
"format": "int32"
},
"foobar": {
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"baz",
"foobar"
]
}
}
}

View file

@ -5,20 +5,20 @@
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "Unit"
"const": "UnitOne"
}
},
"required": [
"tag"
"typeProperty"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "StringMap"
}
@ -27,42 +27,41 @@
"type": "string"
},
"required": [
"tag"
"typeProperty"
]
},
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "UnitStructNewType"
}
},
"required": [
"typeProperty"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"foo": {
"type": "integer",
"format": "int32"
},
"bar": {
"type": "boolean"
},
"typeProperty": {
"type": "string",
"const": "StructNewType"
}
},
"$ref": "#/$defs/Struct",
"required": [
"tag"
]
},
{
"type": "object",
"properties": {
"baz": {
"type": "integer",
"format": "int32"
},
"foobar": {
"type": "boolean"
},
"tag": {
"type": "string",
"const": "StructDenyUnknownFieldsNewType"
}
},
"additionalProperties": false,
"required": [
"tag",
"baz",
"foobar"
"typeProperty",
"foo",
"bar"
]
},
{
@ -75,35 +74,43 @@
"bar": {
"type": "boolean"
},
"tag": {
"typeProperty": {
"type": "string",
"const": "Struct"
}
},
"additionalProperties": false,
"required": [
"tag",
"typeProperty",
"foo",
"bar"
]
}
],
"$defs": {
"Struct": {
},
{
"type": "object",
"properties": {
"foo": {
"type": "integer",
"format": "int32"
},
"bar": {
"type": "boolean"
"typeProperty": {
"type": "string",
"const": "UnitTwo"
}
},
"required": [
"foo",
"bar"
"typeProperty"
],
"additionalProperties": false
},
{
"type": "object",
"format": "int32",
"properties": {
"typeProperty": {
"type": "string",
"const": "WithInt"
}
},
"required": [
"typeProperty"
]
}
}
]
}

View file

@ -5,19 +5,19 @@
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "UnitOne"
}
},
"required": [
"tag"
"typeProperty"
]
},
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "StringMap"
}
@ -26,32 +26,19 @@
"type": "string"
},
"required": [
"tag"
"typeProperty"
]
},
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "UnitStructNewType"
}
},
"required": [
"tag"
]
},
{
"type": "object",
"properties": {
"tag": {
"type": "string",
"const": "StructNewType"
}
},
"$ref": "#/$defs/Struct",
"required": [
"tag"
"typeProperty"
]
},
{
@ -64,13 +51,34 @@
"bar": {
"type": "boolean"
},
"tag": {
"typeProperty": {
"type": "string",
"const": "StructNewType"
}
},
"required": [
"typeProperty",
"foo",
"bar"
]
},
{
"type": "object",
"properties": {
"foo": {
"type": "integer",
"format": "int32"
},
"bar": {
"type": "boolean"
},
"typeProperty": {
"type": "string",
"const": "Struct"
}
},
"required": [
"tag",
"typeProperty",
"foo",
"bar"
]
@ -78,32 +86,27 @@
{
"type": "object",
"properties": {
"tag": {
"typeProperty": {
"type": "string",
"const": "UnitTwo"
}
},
"required": [
"tag"
"typeProperty"
]
}
],
"$defs": {
"Struct": {
},
{
"type": "object",
"format": "int32",
"properties": {
"foo": {
"type": "integer",
"format": "int32"
},
"bar": {
"type": "boolean"
"typeProperty": {
"type": "string",
"const": "WithInt"
}
},
"required": [
"foo",
"bar"
"typeProperty"
]
}
}
]
}

View file

@ -0,0 +1,26 @@
{
"$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
}
]
}

View file

@ -0,0 +1,26 @@
{
"$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
}
]
}

View file

@ -0,0 +1,26 @@
{
"$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
}
]
}

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "EnumWithReprAttr",
"title": "Renamed",
"description": "Description from comment",
"type": "integer",
"enum": [

View file

@ -1,9 +1,12 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Enum",
"type": "string",
"type": "integer",
"enum": [
"Included1",
"Included2"
0,
1,
5,
6,
3
]
}

View file

@ -0,0 +1,45 @@
{
"$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
}
]
}

View file

@ -0,0 +1,42 @@
{
"$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"
]
}
]
}

View file

@ -28,6 +28,7 @@
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"foo",
"bar"
@ -47,17 +48,9 @@
"minItems": 2,
"maxItems": 2
},
{
"type": "null"
},
{
"type": "integer",
"format": "uint64",
"minimum": 0
},
{
"type": "string",
"pattern": "^\\d+ (true|false)$"
"format": "int32"
}
],
"$defs": {

View file

@ -12,10 +12,10 @@
}
},
{
"$ref": "#/$defs/Struct"
"$ref": "#/$defs/UnitStruct"
},
{
"$ref": "#/$defs/StructDenyUnknownFields"
"$ref": "#/$defs/Struct"
},
{
"type": "object",
@ -28,14 +28,34 @@
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"foo",
"bar"
]
},
{
"type": "array",
"prefixItems": [
{
"type": "integer",
"format": "int32"
},
{
"type": "boolean"
}
],
"minItems": 2,
"maxItems": 2
},
{
"type": "integer",
"format": "int32"
}
],
"$defs": {
"UnitStruct": {
"type": "null"
},
"Struct": {
"type": "object",
"properties": {
@ -51,23 +71,6 @@
"foo",
"bar"
]
},
"StructDenyUnknownFields": {
"type": "object",
"properties": {
"baz": {
"type": "integer",
"format": "int32"
},
"foobar": {
"type": "boolean"
}
},
"additionalProperties": false,
"required": [
"baz",
"foobar"
]
}
}
}

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Container",
"title": "Flat",
"type": "object",
"properties": {
"f": {

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ContainerDenyUnknownFields",
"title": "FlatDenyUnknownFields",
"type": "object",
"properties": {
"f": {

View file

@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ContainerDenyUnknownFields",
"title": "FlatDenyUnknownFields",
"type": "object",
"properties": {
"f": {

View file

@ -0,0 +1,18 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Set_of_Foo",
"type": "array",
"uniqueItems": true,
"items": {
"$ref": "#/$defs/Foo"
},
"$defs": {
"Foo": {
"type": "string",
"enum": [
"Bar",
"Baz"
]
}
}
}

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "AdjacentEnum",
"title": "Adjacent",
"oneOf": [
{
"type": "object",

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ExternalEnum",
"title": "External",
"oneOf": [
{
"type": "string",

View file

@ -1,30 +1,30 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "InternalEnum",
"title": "Internal",
"oneOf": [
{
"type": "object",
"properties": {
"t": {
"typeProperty": {
"type": "string",
"const": "Unit"
}
},
"required": [
"t"
"typeProperty"
],
"foo": "bar"
},
{
"type": "object",
"properties": {
"t": {
"typeProperty": {
"type": "string",
"const": "NewType"
}
},
"required": [
"t"
"typeProperty"
],
"foo": "bar"
},
@ -38,13 +38,13 @@
"b": {
"type": "boolean"
},
"t": {
"typeProperty": {
"type": "string",
"const": "Struct"
}
},
"required": [
"t",
"typeProperty",
"i",
"b"
],

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "UntaggedEnum",
"title": "Untagged",
"anyOf": [
{
"type": "null",

View file

@ -7,10 +7,7 @@
"foo": "bar"
},
"int": {
"type": [
"number",
"string"
],
"type": "overridden",
"format": "int32"
}
},
@ -18,6 +15,7 @@
"value",
"int"
],
"msg": "hello world",
"obj": {
"array": [
null,

View file

@ -13,6 +13,10 @@
"s": {
"type": "string"
},
"os": {
"type": "string",
"default": ""
},
"v": {
"type": "array",
"items": {
@ -24,6 +28,7 @@
"required": [
"f",
"b",
"s",
"v"
]
}

View file

@ -5,6 +5,12 @@
"zero": {
"type": "integer"
},
"one": {
"type": "integer"
},
"minusOne": {
"type": "integer"
},
"zeroPointZero": {
"type": "number"
},
@ -15,15 +21,11 @@
"object": {
"type": "object",
"properties": {
"strings": {
"array": {
"type": "array",
"items": {
"type": "string"
}
},
"mixed": {
"type": "array",
"items": true
}
}
}
@ -31,17 +33,15 @@
"examples": [
{
"zero": 0,
"one": 1,
"minusOne": -1,
"zeroPointZero": 0.0,
"bool": true,
"null": null,
"object": {
"strings": [
"array": [
"foo",
"bar"
],
"mixed": [
1,
true
]
}
}

View file

@ -1,5 +1,5 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "MyStruct",
"type": "object",
"properties": {
@ -22,7 +22,7 @@
"my_vec": {
"type": "array",
"items": {
"type": "number"
"type": "string"
}
},
"my_empty_map": {
@ -35,7 +35,9 @@
},
"my_tuple": {
"type": "array",
"prefixItems": [
"minItems": 2,
"maxItems": 2,
"items": [
{
"type": "string",
"minLength": 1,
@ -44,9 +46,7 @@
{
"type": "integer"
}
],
"maxItems": 2,
"minItems": 2
]
}
}
}
@ -58,12 +58,11 @@
"myNullableEnum": null,
"myInnerStruct": {
"my_map": {
"k": 1.23
"": 0.0
},
"my_vec": [
1.0,
2.0,
3.0
"hello",
"world"
],
"my_empty_map": {},
"my_empty_vec": [],

View file

@ -0,0 +1,76 @@
{
"$schema": "http://json-schema.org/draft-07/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
]
}
}
]
}

View file

@ -24,7 +24,7 @@
"my_vec": {
"type": "array",
"items": {
"type": "number"
"type": "string"
}
},
"my_empty_map": {
@ -59,12 +59,11 @@
"myNullableEnum": null,
"myInnerStruct": {
"my_map": {
"k": 1.23
"": 0.0
},
"my_vec": [
1.0,
2.0,
3.0
"hello",
"world"
],
"my_empty_map": {},
"my_empty_vec": [],

View file

@ -1,25 +1,25 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "ValidateAttrStruct",
"title": "Struct",
"type": "object",
"properties": {
"min_max": {
"type": "number",
"format": "float",
"minimum": 1.0,
"maximum": 100.0
"minimum": 0.01,
"maximum": 100
},
"min_max2": {
"type": "number",
"format": "float",
"minimum": 1.0,
"maximum": 10.0
"minimum": 1,
"maximum": 1000
},
"regex_str": {
"regex_str1": {
"type": "string",
"pattern": "^[Hh]ello"
"pattern": "^[Hh]ello\\b"
},
"contains_str": {
"contains_str1": {
"type": "string",
"pattern": "substring\\.\\.\\."
},
@ -36,10 +36,16 @@
"minLength": 1,
"maxLength": 100
},
"non_empty_str2": {
"type": "string",
"minLength": 1,
"maxLength": 1000
},
"pair": {
"type": "array",
"items": {
"type": "string"
"type": "integer",
"format": "int32"
},
"minItems": 2,
"maxItems": 2
@ -49,19 +55,18 @@
},
"x": {
"type": "integer",
"format": "int32",
"minimum": -100,
"maximum": 100
"format": "int32"
}
},
"required": [
"min_max",
"min_max2",
"regex_str",
"contains_str",
"regex_str1",
"contains_str1",
"email_address",
"homepage",
"non_empty_str",
"non_empty_str2",
"pair",
"required_option",
"x"

View file

@ -1,6 +1,6 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GardeAttrNewType",
"title": "NewType",
"type": "integer",
"format": "uint8",
"minimum": 0,

View file

@ -1,25 +1,25 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "GardeAttrStruct",
"title": "Struct2",
"type": "object",
"properties": {
"min_max": {
"type": "number",
"format": "float",
"minimum": 1.0,
"maximum": 100.0
"minimum": 0.01,
"maximum": 100
},
"min_max2": {
"type": "number",
"format": "float",
"minimum": 1.0,
"maximum": 10.0
"minimum": 1,
"maximum": 1000
},
"regex_str": {
"regex_str1": {
"type": "string",
"pattern": "^[Hh]ello"
"pattern": "^[Hh]ello\\b"
},
"contains_str": {
"contains_str1": {
"type": "string",
"pattern": "substring\\.\\.\\."
},
@ -34,13 +34,18 @@
"non_empty_str": {
"type": "string",
"minLength": 1,
"maxLength": 10
"maxLength": 100
},
"non_empty_str2": {
"type": "string",
"minLength": 1,
"maxLength": 1000
},
"pair": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
"type": "integer",
"format": "int32"
},
"minItems": 2,
"maxItems": 2
@ -50,19 +55,18 @@
},
"x": {
"type": "integer",
"format": "int32",
"minimum": -100,
"maximum": 100
"format": "int32"
}
},
"required": [
"min_max",
"min_max2",
"regex_str",
"contains_str",
"regex_str1",
"contains_str1",
"email_address",
"homepage",
"non_empty_str",
"non_empty_str2",
"pair",
"required_option",
"x"

Some files were not shown because too many files have changed in this diff Show more