Merge branch 'master' into validate
This commit is contained in:
commit
b68132f17d
31 changed files with 440 additions and 143 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,5 +1,17 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.8.4] - **In-dev**
|
||||||
|
### Added:
|
||||||
|
- `#[schemars(schema_with = "...")]` attribute can now be set on enum variants.
|
||||||
|
|
||||||
|
## [0.8.3] - 2021-04-05
|
||||||
|
### Added:
|
||||||
|
- Support for `#[schemars(crate = "...")]` attribute to allow deriving JsonSchema when the schemars crate is aliased to a different name (https://github.com/GREsau/schemars/pull/55 / https://github.com/GREsau/schemars/pull/80)
|
||||||
|
- Implement `JsonSchema` for `bytes::Bytes` and `bytes::BytesMut` (https://github.com/GREsau/schemars/pull/68)
|
||||||
|
|
||||||
|
### Fixed:
|
||||||
|
- Fix deriving JsonSchema on types defined inside macros (https://github.com/GREsau/schemars/issues/59 / https://github.com/GREsau/schemars/issues/66 / https://github.com/GREsau/schemars/pull/79)
|
||||||
|
|
||||||
## [0.8.2] - 2021-03-27
|
## [0.8.2] - 2021-03-27
|
||||||
### Added:
|
### Added:
|
||||||
- Enable generating a schema from any serializable value using `schema_for_value!(...)` macro or `SchemaGenerator::root_schema_for_value()`/`SchemaGenerator::into_root_schema_for_value()` methods (https://github.com/GREsau/schemars/pull/75)
|
- Enable generating a schema from any serializable value using `schema_for_value!(...)` macro or `SchemaGenerator::root_schema_for_value()`/`SchemaGenerator::into_root_schema_for_value()` methods (https://github.com/GREsau/schemars/pull/75)
|
||||||
|
|
|
@ -273,3 +273,4 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
|
||||||
- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
|
- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
|
||||||
- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
|
- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
|
||||||
- [`url`](https://crates.io/crates/url) (^2.0)
|
- [`url`](https://crates.io/crates/url) (^2.0)
|
||||||
|
- [`bytes`](https://crates.io/crates/bytes) (^1.0)
|
||||||
|
|
|
@ -38,6 +38,7 @@ TABLE OF CONTENTS
|
||||||
- [`title` / `description`](#title-description)
|
- [`title` / `description`](#title-description)
|
||||||
- [`example`](#example)
|
- [`example`](#example)
|
||||||
- [`deprecated`](#deprecated)
|
- [`deprecated`](#deprecated)
|
||||||
|
- [`crate`](#crate)
|
||||||
- [Doc Comments (`doc`)](#doc)
|
- [Doc Comments (`doc`)](#doc)
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
@ -182,6 +183,13 @@ Set on a container, variant or field to include the result of the given function
|
||||||
|
|
||||||
Set the Rust built-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/an-attribute-for-deprecation.html) attribute on a struct, enum, field or variant to set the generated schema's `deprecated` keyword to `true`.
|
Set the Rust built-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/an-attribute-for-deprecation.html) attribute on a struct, enum, field or variant to set the generated schema's `deprecated` keyword to `true`.
|
||||||
|
|
||||||
|
<h3 id="crate">
|
||||||
|
|
||||||
|
`#[schemars(crate = "other_crate::schemars")]`
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
Set the path to the schemars crate instance the generated code should depend on. This is mostly useful for other crates that depend on schemars in their macros.
|
||||||
|
|
||||||
<h3 id="doc">
|
<h3 id="doc">
|
||||||
|
|
||||||
Doc Comments (`#[doc = "..."]`)
|
Doc Comments (`#[doc = "..."]`)
|
||||||
|
|
|
@ -27,3 +27,4 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
|
||||||
- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
|
- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
|
||||||
- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
|
- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
|
||||||
- [`url`](https://crates.io/crates/url) (^2.0)
|
- [`url`](https://crates.io/crates/url) (^2.0)
|
||||||
|
- [`bytes`](https://crates.io/crates/bytes) (^1.0)
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = "schemars"
|
||||||
description = "Generate JSON Schemas from Rust code"
|
description = "Generate JSON Schemas from Rust code"
|
||||||
homepage = "https://graham.cool/schemars/"
|
homepage = "https://graham.cool/schemars/"
|
||||||
repository = "https://github.com/GREsau/schemars"
|
repository = "https://github.com/GREsau/schemars"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
@ -13,7 +13,7 @@ categories = ["encoding"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
schemars_derive = { version = "=0.8.2", optional = true, path = "../schemars_derive" }
|
schemars_derive = { version = "=0.8.3", optional = true, path = "../schemars_derive" }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
dyn-clone = "1.0"
|
dyn-clone = "1.0"
|
||||||
|
@ -25,6 +25,7 @@ uuid = { version = "0.8", default-features = false, optional = true }
|
||||||
smallvec = { version = "1.0", optional = true }
|
smallvec = { version = "1.0", optional = true }
|
||||||
arrayvec = { version = "0.5", default-features = false, optional = true }
|
arrayvec = { version = "0.5", default-features = false, optional = true }
|
||||||
url = { version = "2.0", default-features = false, optional = true }
|
url = { version = "2.0", default-features = false, optional = true }
|
||||||
|
bytes = { version = "1.0", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6.1"
|
pretty_assertions = "0.6.1"
|
||||||
|
@ -66,6 +67,10 @@ required-features = ["uuid"]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
required-features = ["smallvec"]
|
required-features = ["smallvec"]
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "bytes"
|
||||||
|
required-features = ["bytes"]
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
required-features = ["arrayvec"]
|
required-features = ["arrayvec"]
|
||||||
|
|
55
schemars/src/_private.rs
Normal file
55
schemars/src/_private.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use crate::flatten::Merge;
|
||||||
|
use crate::gen::SchemaGenerator;
|
||||||
|
use crate::schema::{Metadata, Schema, SchemaObject};
|
||||||
|
use crate::JsonSchema;
|
||||||
|
|
||||||
|
// Helper for generating schemas for flattened `Option` fields.
|
||||||
|
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(gen: &mut SchemaGenerator) -> Schema {
|
||||||
|
let mut schema = T::_schemars_private_non_optional_json_schema(gen);
|
||||||
|
if T::_schemars_private_is_option() {
|
||||||
|
if let Schema::Object(SchemaObject {
|
||||||
|
object: Some(ref mut object_validation),
|
||||||
|
..
|
||||||
|
}) = schema
|
||||||
|
{
|
||||||
|
object_validation.required.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schema
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper for generating schemas for `Option` fields.
|
||||||
|
pub fn add_schema_as_property<T: ?Sized + JsonSchema>(
|
||||||
|
gen: &mut SchemaGenerator,
|
||||||
|
parent: &mut SchemaObject,
|
||||||
|
name: String,
|
||||||
|
metadata: Option<Metadata>,
|
||||||
|
required: Option<bool>,
|
||||||
|
) {
|
||||||
|
let is_type_option = T::_schemars_private_is_option();
|
||||||
|
let required = required.unwrap_or(!is_type_option);
|
||||||
|
let mut schema = if required && is_type_option {
|
||||||
|
T::_schemars_private_non_optional_json_schema(gen)
|
||||||
|
} else {
|
||||||
|
gen.subschema_for::<T>()
|
||||||
|
};
|
||||||
|
schema = apply_metadata(schema, metadata);
|
||||||
|
|
||||||
|
let object = parent.object();
|
||||||
|
if required {
|
||||||
|
object.required.insert(name.clone());
|
||||||
|
}
|
||||||
|
object.properties.insert(name, schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_metadata(schema: Schema, metadata: Option<Metadata>) -> Schema {
|
||||||
|
match metadata {
|
||||||
|
None => schema,
|
||||||
|
Some(ref metadata) if *metadata == Metadata::default() => schema,
|
||||||
|
Some(metadata) => {
|
||||||
|
let mut schema_obj = schema.into_object();
|
||||||
|
schema_obj.metadata = Some(Box::new(metadata)).merge(schema_obj.metadata);
|
||||||
|
Schema::Object(schema_obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ There are two main types in this module:two main types in this module:
|
||||||
* [`SchemaGenerator`], which manages the generation of a schema document.
|
* [`SchemaGenerator`], which manages the generation of a schema document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::flatten::Merge;
|
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use crate::{visit::*, JsonSchema, Map};
|
use crate::{visit::*, JsonSchema, Map};
|
||||||
use dyn_clone::DynClone;
|
use dyn_clone::DynClone;
|
||||||
|
@ -422,22 +421,6 @@ impl SchemaGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is only public for use by schemars_derive.
|
|
||||||
///
|
|
||||||
/// It should not be considered part of the public API.
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn apply_metadata(&self, schema: Schema, metadata: Option<Metadata>) -> Schema {
|
|
||||||
match metadata {
|
|
||||||
None => schema,
|
|
||||||
Some(ref metadata) if *metadata == Metadata::default() => schema,
|
|
||||||
Some(metadata) => {
|
|
||||||
let mut schema_obj = schema.into_object();
|
|
||||||
schema_obj.metadata = Some(Box::new(metadata)).merge(schema_obj.metadata);
|
|
||||||
Schema::Object(schema_obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn json_schema_internal<T: ?Sized + JsonSchema>(&mut self, name: &str) -> Schema {
|
fn json_schema_internal<T: ?Sized + JsonSchema>(&mut self, name: &str) -> Schema {
|
||||||
struct PendingSchemaState<'a> {
|
struct PendingSchemaState<'a> {
|
||||||
gen: &'a mut SchemaGenerator,
|
gen: &'a mut SchemaGenerator,
|
||||||
|
|
7
schemars/src/json_schema_impls/bytes.rs
Normal file
7
schemars/src/json_schema_impls/bytes.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use crate::gen::SchemaGenerator;
|
||||||
|
use crate::schema::*;
|
||||||
|
use crate::JsonSchema;
|
||||||
|
use bytes::{Bytes, BytesMut};
|
||||||
|
|
||||||
|
forward_impl!((JsonSchema for Bytes) => Vec<u8>);
|
||||||
|
forward_impl!((JsonSchema for BytesMut) => Vec<u8>);
|
|
@ -45,34 +45,12 @@ impl<T: JsonSchema> JsonSchema for Option<T> {
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema_for_flatten(gen: &mut SchemaGenerator) -> Schema {
|
fn _schemars_private_non_optional_json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
let mut schema = T::json_schema_for_flatten(gen);
|
T::_schemars_private_non_optional_json_schema(gen)
|
||||||
if let Schema::Object(SchemaObject {
|
|
||||||
object: Some(ref mut object_validation),
|
|
||||||
..
|
|
||||||
}) = schema
|
|
||||||
{
|
|
||||||
object_validation.required.clear();
|
|
||||||
}
|
|
||||||
schema
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_schema_as_property(
|
fn _schemars_private_is_option() -> bool {
|
||||||
gen: &mut SchemaGenerator,
|
true
|
||||||
parent: &mut SchemaObject,
|
|
||||||
name: String,
|
|
||||||
metadata: Option<Metadata>,
|
|
||||||
required: Option<bool>,
|
|
||||||
) {
|
|
||||||
if required == Some(true) {
|
|
||||||
T::add_schema_as_property(gen, parent, name, metadata, required)
|
|
||||||
} else {
|
|
||||||
let mut schema = gen.subschema_for::<Self>();
|
|
||||||
schema = gen.apply_metadata(schema, metadata);
|
|
||||||
|
|
||||||
let object = parent.object();
|
|
||||||
object.properties.insert(name, schema);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,18 +21,12 @@ macro_rules! forward_impl {
|
||||||
<$target>::json_schema(gen)
|
<$target>::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema_for_flatten(gen: &mut SchemaGenerator) -> Schema {
|
fn _schemars_private_non_optional_json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
<$target>::json_schema_for_flatten(gen)
|
<$target>::_schemars_private_non_optional_json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_schema_as_property(
|
fn _schemars_private_is_option() -> bool {
|
||||||
gen: &mut SchemaGenerator,
|
<$target>::_schemars_private_is_option()
|
||||||
parent: &mut crate::schema::SchemaObject,
|
|
||||||
name: String,
|
|
||||||
metadata: Option<crate::schema::Metadata>,
|
|
||||||
required: Option<bool>,
|
|
||||||
) {
|
|
||||||
<$target>::add_schema_as_property(gen, parent, name, metadata, required)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -46,6 +40,8 @@ mod array;
|
||||||
mod arrayvec;
|
mod arrayvec;
|
||||||
#[cfg(std_atomic)]
|
#[cfg(std_atomic)]
|
||||||
mod atomic;
|
mod atomic;
|
||||||
|
#[cfg(feature = "bytes")]
|
||||||
|
mod bytes;
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
mod chrono;
|
mod chrono;
|
||||||
mod core;
|
mod core;
|
||||||
|
|
|
@ -9,7 +9,9 @@ macro_rules! tuple_impls {
|
||||||
no_ref_schema!();
|
no_ref_schema!();
|
||||||
|
|
||||||
fn schema_name() -> String {
|
fn schema_name() -> String {
|
||||||
["Tuple_of".to_owned()$(, $name::schema_name())+].join("_and_")
|
let mut name = "Tuple_of_".to_owned();
|
||||||
|
name.push_str(&[$($name::schema_name()),+].join("_and_"));
|
||||||
|
name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
fn json_schema(gen: &mut SchemaGenerator) -> Schema {
|
||||||
|
|
|
@ -268,6 +268,7 @@ Schemars can implement `JsonSchema` on types from several popular crates, enable
|
||||||
- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
|
- [`smallvec`](https://crates.io/crates/smallvec) (^1.0)
|
||||||
- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
|
- [`arrayvec`](https://crates.io/crates/arrayvec) (^0.5)
|
||||||
- [`url`](https://crates.io/crates/url) (^2.0)
|
- [`url`](https://crates.io/crates/url) (^2.0)
|
||||||
|
- [`bytes`](https://crates.io/crates/bytes) (^1.0)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// The map type used by schemars types.
|
/// The map type used by schemars types.
|
||||||
|
@ -300,6 +301,10 @@ mod ser;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
/// This module is only public for use by `schemars_derive`. It should not need to be used by code
|
||||||
|
/// outside of `schemars`, and should not be considered part of the public API.
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub mod _private;
|
||||||
pub mod gen;
|
pub mod gen;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
@ -313,7 +318,7 @@ pub use schemars_derive::*;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use serde_json as _serde_json;
|
pub use serde_json as _serde_json;
|
||||||
|
|
||||||
use schema::{Schema, SchemaObject};
|
use schema::Schema;
|
||||||
|
|
||||||
/// A type which can be described as a JSON Schema document.
|
/// A type which can be described as a JSON Schema document.
|
||||||
///
|
///
|
||||||
|
@ -356,35 +361,16 @@ pub trait JsonSchema {
|
||||||
/// This should not return a `$ref` schema.
|
/// This should not return a `$ref` schema.
|
||||||
fn json_schema(gen: &mut gen::SchemaGenerator) -> Schema;
|
fn json_schema(gen: &mut gen::SchemaGenerator) -> Schema;
|
||||||
|
|
||||||
/// Helper for generating schemas for flattened `Option` fields.
|
// TODO document and bring into public API?
|
||||||
///
|
|
||||||
/// This should not need to be called or implemented by code outside of `schemars`,
|
|
||||||
/// and should not be considered part of the public API.
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn json_schema_for_flatten(gen: &mut gen::SchemaGenerator) -> Schema {
|
fn _schemars_private_non_optional_json_schema(gen: &mut gen::SchemaGenerator) -> Schema {
|
||||||
Self::json_schema(gen)
|
Self::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper for generating schemas for `Option` fields.
|
// TODO document and bring into public API?
|
||||||
///
|
|
||||||
/// This should not need to be called or implemented by code outside of `schemars`,
|
|
||||||
/// and should not be considered part of the public API.
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
fn add_schema_as_property(
|
fn _schemars_private_is_option() -> bool {
|
||||||
gen: &mut gen::SchemaGenerator,
|
false
|
||||||
parent: &mut SchemaObject,
|
|
||||||
name: String,
|
|
||||||
metadata: Option<schema::Metadata>,
|
|
||||||
required: Option<bool>,
|
|
||||||
) {
|
|
||||||
let mut schema = gen.subschema_for::<Self>();
|
|
||||||
schema = gen.apply_metadata(schema, metadata);
|
|
||||||
|
|
||||||
let object = parent.object();
|
|
||||||
if required.unwrap_or(true) {
|
|
||||||
object.required.insert(name.clone());
|
|
||||||
}
|
|
||||||
object.properties.insert(name, schema);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
schemars/tests/bytes.rs
Normal file
8
schemars/tests/bytes.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
mod util;
|
||||||
|
use bytes::{Bytes, BytesMut};
|
||||||
|
use util::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bytes() -> TestResult {
|
||||||
|
test_default_generated_schema::<(Bytes, BytesMut)>("bytes")
|
||||||
|
}
|
19
schemars/tests/crate_alias.rs
Normal file
19
schemars/tests/crate_alias.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
mod util;
|
||||||
|
use ::schemars as not_schemars;
|
||||||
|
use util::*;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use std as schemars;
|
||||||
|
|
||||||
|
#[derive(Debug, not_schemars::JsonSchema)]
|
||||||
|
#[schemars(crate = "not_schemars")]
|
||||||
|
pub struct Struct {
|
||||||
|
/// This is a document
|
||||||
|
foo: i32,
|
||||||
|
bar: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_crate_alias() -> TestResult {
|
||||||
|
test_default_generated_schema::<Struct>("crate_alias")
|
||||||
|
}
|
|
@ -14,8 +14,8 @@ pub struct Struct {
|
||||||
bar: bool,
|
bar: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outer container should always have additionalPropreties: false
|
// Outer container should always have additionalProperties: false
|
||||||
// `Struct` variant should have additionalPropreties: false
|
// `Struct` variant should have additionalProperties: false
|
||||||
#[derive(Debug, JsonSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
|
#[schemars(rename_all = "camelCase", deny_unknown_fields)]
|
||||||
pub enum External {
|
pub enum External {
|
||||||
|
@ -38,7 +38,7 @@ fn enum_external_tag() -> TestResult {
|
||||||
test_default_generated_schema::<External>("enum-external-duf")
|
test_default_generated_schema::<External>("enum-external-duf")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only `Struct` variant should have additionalPropreties: false
|
// Only `Struct` variant should have additionalProperties: false
|
||||||
#[derive(Debug, JsonSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(tag = "typeProperty", deny_unknown_fields)]
|
#[schemars(tag = "typeProperty", deny_unknown_fields)]
|
||||||
pub enum Internal {
|
pub enum Internal {
|
||||||
|
@ -60,7 +60,7 @@ fn enum_internal_tag() -> TestResult {
|
||||||
test_default_generated_schema::<Internal>("enum-internal-duf")
|
test_default_generated_schema::<Internal>("enum-internal-duf")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only `Struct` variant should have additionalPropreties: false
|
// Only `Struct` variant should have additionalProperties: false
|
||||||
#[derive(Debug, JsonSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(untagged, deny_unknown_fields)]
|
#[schemars(untagged, deny_unknown_fields)]
|
||||||
pub enum Untagged {
|
pub enum Untagged {
|
||||||
|
@ -82,7 +82,7 @@ fn enum_untagged() -> TestResult {
|
||||||
test_default_generated_schema::<Untagged>("enum-untagged-duf")
|
test_default_generated_schema::<Untagged>("enum-untagged-duf")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outer container and `Struct` variant should have additionalPropreties: false
|
// Outer container and `Struct` variant should have additionalProperties: false
|
||||||
#[derive(Debug, JsonSchema)]
|
#[derive(Debug, JsonSchema)]
|
||||||
#[schemars(tag = "t", content = "c", deny_unknown_fields)]
|
#[schemars(tag = "t", content = "c", deny_unknown_fields)]
|
||||||
pub enum Adjacent {
|
pub enum Adjacent {
|
||||||
|
|
25
schemars/tests/expected/bytes.json
Normal file
25
schemars/tests/expected/bytes.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Tuple_of_Array_of_uint8_and_Array_of_uint8",
|
||||||
|
"type": "array",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint8",
|
||||||
|
"minimum": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint8",
|
||||||
|
"minimum": 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxItems": 2,
|
||||||
|
"minItems": 2
|
||||||
|
}
|
19
schemars/tests/expected/crate_alias.json
Normal file
19
schemars/tests/expected/crate_alias.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Struct",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"bar",
|
||||||
|
"foo"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"foo": {
|
||||||
|
"description": "This is a document",
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
schemars/tests/expected/macro_built_enum.json
Normal file
23
schemars/tests/expected/macro_built_enum.json
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "OuterEnum",
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"InnerStruct"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"InnerStruct": {
|
||||||
|
"$ref": "#/definitions/InnerStruct"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"definitions": {
|
||||||
|
"InnerStruct": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
schemars/tests/expected/macro_built_struct.json
Normal file
20
schemars/tests/expected/macro_built_struct.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "A",
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"v",
|
||||||
|
"x"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"x": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint8",
|
||||||
|
"minimum": 0.0
|
||||||
|
},
|
||||||
|
"v": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -74,6 +74,24 @@
|
||||||
"minItems": 2
|
"minItems": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"c",
|
||||||
|
"t"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"t": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Unit"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"c": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -56,6 +56,18 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"unit"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"unit": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -36,6 +36,23 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"object"
|
||||||
|
],
|
||||||
|
"required": [
|
||||||
|
"typeProperty"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"typeProperty": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"Unit"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -29,6 +29,9 @@
|
||||||
],
|
],
|
||||||
"maxItems": 2,
|
"maxItems": 2,
|
||||||
"minItems": 2
|
"minItems": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
67
schemars/tests/macro.rs
Normal file
67
schemars/tests/macro.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
mod util;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use util::*;
|
||||||
|
|
||||||
|
macro_rules! build_struct {
|
||||||
|
(
|
||||||
|
$id:ident { $($t:tt)* }
|
||||||
|
) => {
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
pub struct $id {
|
||||||
|
x: u8,
|
||||||
|
$($t)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
build_struct!(A { v: i32 });
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macro_built_struct() -> TestResult {
|
||||||
|
test_default_generated_schema::<A>("macro_built_struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! build_enum {
|
||||||
|
(
|
||||||
|
$(#[$outer_derive:meta])*
|
||||||
|
$outer:ident {
|
||||||
|
$($(#[$inner_derive:meta])*
|
||||||
|
$inner:ident {
|
||||||
|
$( $(#[$field_attribute:meta])*
|
||||||
|
$field:ident : $ty:ty),*
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
|
||||||
|
$(
|
||||||
|
$(#[$inner_derive])*
|
||||||
|
pub struct $inner {
|
||||||
|
$(
|
||||||
|
$(#[$field_attribute])*
|
||||||
|
pub $field: $ty
|
||||||
|
),*
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
|
$(#[$outer_derive])*
|
||||||
|
pub enum $outer {
|
||||||
|
$(
|
||||||
|
$inner($inner)
|
||||||
|
),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build_enum!(
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
OuterEnum {
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
InnerStruct {}
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn macro_built_enum() -> TestResult {
|
||||||
|
test_default_generated_schema::<OuterEnum>("macro_built_enum")
|
||||||
|
}
|
|
@ -2,8 +2,6 @@ mod util;
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
// FIXME determine whether schema_with should be allowed on unit variants
|
|
||||||
|
|
||||||
fn schema_fn(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn schema_fn(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
<bool>::json_schema(gen)
|
<bool>::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
@ -23,8 +21,8 @@ pub enum External {
|
||||||
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
|
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
|
||||||
i32,
|
i32,
|
||||||
),
|
),
|
||||||
// #[schemars(schema_with = "schema_fn")]
|
#[schemars(schema_with = "schema_fn")]
|
||||||
// Unit,
|
Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -40,8 +38,8 @@ pub enum Internal {
|
||||||
foo: DoesntImplementJsonSchema,
|
foo: DoesntImplementJsonSchema,
|
||||||
},
|
},
|
||||||
NewType(#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema),
|
NewType(#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema),
|
||||||
// #[schemars(schema_with = "schema_fn")]
|
#[schemars(schema_with = "schema_fn")]
|
||||||
// Unit,
|
Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -61,8 +59,8 @@ pub enum Untagged {
|
||||||
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
|
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
|
||||||
i32,
|
i32,
|
||||||
),
|
),
|
||||||
// #[schemars(schema_with = "schema_fn")]
|
#[schemars(schema_with = "schema_fn")]
|
||||||
// Unit,
|
Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -82,8 +80,8 @@ pub enum Adjacent {
|
||||||
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
|
#[schemars(schema_with = "schema_fn")] DoesntImplementJsonSchema,
|
||||||
i32,
|
i32,
|
||||||
),
|
),
|
||||||
// #[schemars(schema_with = "schema_fn")]
|
#[schemars(schema_with = "schema_fn")]
|
||||||
// Unit,
|
Unit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -3,7 +3,7 @@ name = "schemars_derive"
|
||||||
description = "Macros for #[derive(JsonSchema)], for use with schemars"
|
description = "Macros for #[derive(JsonSchema)], for use with schemars"
|
||||||
homepage = "https://graham.cool/schemars/"
|
homepage = "https://graham.cool/schemars/"
|
||||||
repository = "https://github.com/GREsau/schemars"
|
repository = "https://github.com/GREsau/schemars"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
authors = ["Graham Esau <gesau@hotmail.co.uk>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
|
@ -13,6 +13,10 @@ use syn::Meta::{List, NameValue};
|
||||||
use syn::MetaNameValue;
|
use syn::MetaNameValue;
|
||||||
use syn::NestedMeta::{Lit, Meta};
|
use syn::NestedMeta::{Lit, Meta};
|
||||||
|
|
||||||
|
// FIXME using the same struct for containers+variants+fields means that
|
||||||
|
// with/schema_with are accepted (but ignored) on containers, and
|
||||||
|
// repr/crate_name are accepted (but ignored) on variants and fields etc.
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Attrs {
|
pub struct Attrs {
|
||||||
pub with: Option<WithAttr>,
|
pub with: Option<WithAttr>,
|
||||||
|
@ -21,6 +25,7 @@ pub struct Attrs {
|
||||||
pub deprecated: bool,
|
pub deprecated: bool,
|
||||||
pub examples: Vec<syn::Path>,
|
pub examples: Vec<syn::Path>,
|
||||||
pub repr: Option<syn::Type>,
|
pub repr: Option<syn::Type>,
|
||||||
|
pub crate_name: Option<syn::Path>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -125,6 +130,16 @@ impl Attrs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Meta(NameValue(m)) if m.path.is_ident("crate") && attr_type == "schemars" => {
|
||||||
|
if let Ok(p) = parse_lit_into_path(errors, attr_type, "crate", &m.lit) {
|
||||||
|
if self.crate_name.is_some() {
|
||||||
|
duplicate_error(m)
|
||||||
|
} else {
|
||||||
|
self.crate_name = Some(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ if ignore_errors => {}
|
_ if ignore_errors => {}
|
||||||
|
|
||||||
Meta(meta_item) => {
|
Meta(meta_item) => {
|
||||||
|
|
|
@ -125,11 +125,11 @@ impl ValidationAttrs {
|
||||||
// `schema_object` - the SchemaObject for the struct that contains this field.
|
// `schema_object` - the SchemaObject for the struct that contains this field.
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
if self.required {
|
// if self.required {
|
||||||
statements.push(quote! {
|
// statements.push(quote! {
|
||||||
schema_object.object().required.insert(#field_name.to_owned());
|
// schema_object.object().required.insert(#field_name.to_owned());
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
let mut array_validation = Vec::new();
|
let mut array_validation = Vec::new();
|
||||||
let mut number_validation = Vec::new();
|
let mut number_validation = Vec::new();
|
||||||
|
|
|
@ -14,6 +14,7 @@ mod schema_exprs;
|
||||||
|
|
||||||
use ast::*;
|
use ast::*;
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
|
use syn::spanned::Spanned;
|
||||||
|
|
||||||
#[proc_macro_derive(JsonSchema, attributes(schemars, serde, validate))]
|
#[proc_macro_derive(JsonSchema, attributes(schemars, serde, validate))]
|
||||||
pub fn derive_json_schema_wrapper(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_json_schema_wrapper(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
@ -40,14 +41,20 @@ fn derive_json_schema(
|
||||||
attr::process_serde_attrs(&mut input)?;
|
attr::process_serde_attrs(&mut input)?;
|
||||||
|
|
||||||
let cont = Container::from_ast(&input)?;
|
let cont = Container::from_ast(&input)?;
|
||||||
|
let crate_alias = cont.attrs.crate_name.as_ref().map(|path| {
|
||||||
|
quote_spanned! {path.span()=>
|
||||||
|
use #path as schemars;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let type_name = &cont.ident;
|
let type_name = &cont.ident;
|
||||||
let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
|
||||||
|
|
||||||
if let Some(transparent_field) = cont.transparent_field() {
|
if let Some(transparent_field) = cont.transparent_field() {
|
||||||
let (ty, type_def) = schema_exprs::type_for_schema(transparent_field, 0);
|
let (ty, type_def) = schema_exprs::type_for_field_schema(transparent_field, 0);
|
||||||
return Ok(quote! {
|
return Ok(quote! {
|
||||||
const _: () = {
|
const _: () = {
|
||||||
|
#crate_alias
|
||||||
#type_def
|
#type_def
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
@ -64,18 +71,12 @@ fn derive_json_schema(
|
||||||
<#ty as schemars::JsonSchema>::json_schema(gen)
|
<#ty as schemars::JsonSchema>::json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn json_schema_for_flatten(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
fn _schemars_private_non_optional_json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
|
||||||
<#ty as schemars::JsonSchema>::json_schema_for_flatten(gen)
|
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_schema_as_property(
|
fn _schemars_private_is_option() -> bool {
|
||||||
gen: &mut schemars::gen::SchemaGenerator,
|
<#ty as schemars::JsonSchema>::_schemars_private_is_option()
|
||||||
parent: &mut schemars::schema::SchemaObject,
|
|
||||||
name: String,
|
|
||||||
metadata: Option<schemars::schema::Metadata>,
|
|
||||||
required: Option<bool>,
|
|
||||||
) {
|
|
||||||
<#ty as schemars::JsonSchema>::add_schema_as_property(gen, parent, name, metadata, required)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -122,6 +123,9 @@ fn derive_json_schema(
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
|
const _: () = {
|
||||||
|
#crate_alias
|
||||||
|
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
#[allow(unused_braces)]
|
#[allow(unused_braces)]
|
||||||
impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause {
|
impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause {
|
||||||
|
@ -133,6 +137,7 @@ fn derive_json_schema(
|
||||||
#schema_expr
|
#schema_expr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ impl<'a> SchemaMetadata<'a> {
|
||||||
quote! {
|
quote! {
|
||||||
{
|
{
|
||||||
let schema = #schema_expr;
|
let schema = #schema_expr;
|
||||||
gen.apply_metadata(schema, #self)
|
schemars::_private::apply_metadata(schema, #self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,31 +57,38 @@ pub fn expr_for_repr(cont: &Container) -> Result<TokenStream, syn::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream {
|
fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream {
|
||||||
let (ty, type_def) = type_for_schema(field, 0);
|
let (ty, type_def) = type_for_field_schema(field, 0);
|
||||||
let span = field.original.span();
|
let span = field.original.span();
|
||||||
|
let gen = quote!(gen);
|
||||||
|
|
||||||
if allow_ref {
|
if allow_ref {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
{
|
{
|
||||||
#type_def
|
#type_def
|
||||||
gen.subschema_for::<#ty>()
|
#gen.subschema_for::<#ty>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! {span=>
|
quote_spanned! {span=>
|
||||||
{
|
{
|
||||||
#type_def
|
#type_def
|
||||||
<#ty as schemars::JsonSchema>::json_schema(gen)
|
<#ty as schemars::JsonSchema>::json_schema(#gen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_for_schema(field: &Field, local_id: usize) -> (syn::Type, Option<TokenStream>) {
|
pub fn type_for_field_schema(field: &Field, local_id: usize) -> (syn::Type, Option<TokenStream>) {
|
||||||
match &field.attrs.with {
|
match &field.attrs.with {
|
||||||
None => (field.ty.to_owned(), None),
|
None => (field.ty.to_owned(), None),
|
||||||
Some(WithAttr::Type(ty)) => (ty.to_owned(), None),
|
Some(with_attr) => type_for_schema(with_attr, local_id),
|
||||||
Some(WithAttr::Function(fun)) => {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_for_schema(with_attr: &WithAttr, local_id: usize) -> (syn::Type, Option<TokenStream>) {
|
||||||
|
match with_attr {
|
||||||
|
WithAttr::Type(ty) => (ty.to_owned(), None),
|
||||||
|
WithAttr::Function(fun) => {
|
||||||
let ty_name = format_ident!("_SchemarsSchemaWithFunction{}", local_id);
|
let ty_name = format_ident!("_SchemarsSchemaWithFunction{}", local_id);
|
||||||
let fn_name = fun.segments.last().unwrap().ident.to_string();
|
let fn_name = fun.segments.last().unwrap().ident.to_string();
|
||||||
|
|
||||||
|
@ -315,9 +322,14 @@ fn expr_for_adjacent_tagged_enum<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_for_untagged_enum_variant(variant: &Variant, deny_unknown_fields: bool) -> TokenStream {
|
fn expr_for_untagged_enum_variant(variant: &Variant, deny_unknown_fields: bool) -> TokenStream {
|
||||||
if let Some(WithAttr::Type(with)) = &variant.attrs.with {
|
if let Some(with_attr) = &variant.attrs.with {
|
||||||
|
let (ty, type_def) = type_for_schema(with_attr, 0);
|
||||||
|
let gen = quote!(gen);
|
||||||
return quote_spanned! {variant.original.span()=>
|
return quote_spanned! {variant.original.span()=>
|
||||||
gen.subschema_for::<#with>()
|
{
|
||||||
|
#type_def
|
||||||
|
#gen.subschema_for::<#ty>()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,9 +345,14 @@ fn expr_for_untagged_enum_variant_for_flatten(
|
||||||
variant: &Variant,
|
variant: &Variant,
|
||||||
deny_unknown_fields: bool,
|
deny_unknown_fields: bool,
|
||||||
) -> Option<TokenStream> {
|
) -> Option<TokenStream> {
|
||||||
if let Some(WithAttr::Type(with)) = &variant.attrs.with {
|
if let Some(with_attr) = &variant.attrs.with {
|
||||||
|
let (ty, type_def) = type_for_schema(with_attr, 0);
|
||||||
|
let gen = quote!(gen);
|
||||||
return Some(quote_spanned! {variant.original.span()=>
|
return Some(quote_spanned! {variant.original.span()=>
|
||||||
<#with as schemars::JsonSchema>::json_schema(gen)
|
{
|
||||||
|
#type_def
|
||||||
|
<#ty as schemars::JsonSchema>::json_schema(#gen)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +379,7 @@ fn expr_for_tuple_struct(fields: &[Field]) -> TokenStream {
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|f| !f.serde_attrs.skip_deserializing())
|
.filter(|f| !f.serde_attrs.skip_deserializing())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, f)| type_for_schema(f, i))
|
.map(|(i, f)| type_for_field_schema(f, i))
|
||||||
.unzip();
|
.unzip();
|
||||||
quote! {
|
quote! {
|
||||||
{
|
{
|
||||||
|
@ -409,20 +426,16 @@ fn expr_for_struct(
|
||||||
..SchemaMetadata::from_attrs(&field.attrs)
|
..SchemaMetadata::from_attrs(&field.attrs)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (ty, type_def) = type_for_schema(field, type_defs.len());
|
let (ty, type_def) = type_for_field_schema(field, type_defs.len());
|
||||||
if let Some(type_def) = type_def {
|
if let Some(type_def) = type_def {
|
||||||
type_defs.push(type_def);
|
type_defs.push(type_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let args = quote!(gen, &mut schema_object, #name.to_owned(), #metadata, #required);
|
||||||
let validation = field.validation_attrs.validation_statements(&name);
|
let validation = field.validation_attrs.validation_statements(&name);
|
||||||
|
|
||||||
quote_spanned! {ty.span()=>
|
quote_spanned! {ty.span()=>
|
||||||
<#ty as schemars::JsonSchema>::add_schema_as_property(
|
schemars::_private::add_schema_as_property::<#ty>(#args);
|
||||||
gen,
|
|
||||||
&mut schema_object,
|
|
||||||
#name.to_owned(),
|
|
||||||
#metadata,
|
|
||||||
#required);
|
|
||||||
#validation
|
#validation
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -431,13 +444,14 @@ fn expr_for_struct(
|
||||||
let flattens: Vec<_> = flattened_fields
|
let flattens: Vec<_> = flattened_fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|field| {
|
.map(|field| {
|
||||||
let (ty, type_def) = type_for_schema(field, type_defs.len());
|
let (ty, type_def) = type_for_field_schema(field, type_defs.len());
|
||||||
if let Some(type_def) = type_def {
|
if let Some(type_def) = type_def {
|
||||||
type_defs.push(type_def);
|
type_defs.push(type_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let gen = quote!(gen);
|
||||||
quote_spanned! {ty.span()=>
|
quote_spanned! {ty.span()=>
|
||||||
.flatten(<#ty as schemars::JsonSchema>::json_schema_for_flatten(gen))
|
.flatten(schemars::_private::json_schema_for_flatten::<#ty>(#gen))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue