Allow schema_with attr on enum variants
This commit is contained in:
parent
2d38db903a
commit
5dc644000c
9 changed files with 93 additions and 27 deletions
|
@ -1,5 +1,9 @@
|
||||||
# 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
|
## [0.8.3] - 2021-04-05
|
||||||
### Added:
|
### 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)
|
- 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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -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]
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn derive_json_schema(
|
||||||
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
|
#crate_alias
|
||||||
|
|
|
@ -57,7 +57,7 @@ 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);
|
let gen = quote!(gen);
|
||||||
|
|
||||||
|
@ -78,11 +78,17 @@ fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
|
@ -316,10 +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);
|
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>()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,10 +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);
|
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)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,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! {
|
||||||
{
|
{
|
||||||
|
@ -411,7 +425,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -427,7 +441,7 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue