Process validation attributes in tuple structs

This commit is contained in:
Graham Esau 2021-04-16 13:56:26 +01:00
parent 31a5893d10
commit 9e507272da
3 changed files with 55 additions and 10 deletions

View file

@ -0,0 +1,18 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Tuple",
"type": "array",
"items": [
{
"type": "integer",
"format": "uint8",
"maximum": 10.0,
"minimum": 0.0
},
{
"type": "boolean"
}
],
"maxItems": 2,
"minItems": 2
}

View file

@ -47,6 +47,17 @@ fn validate() -> TestResult {
test_default_generated_schema::<Struct>("validate") test_default_generated_schema::<Struct>("validate")
} }
#[derive(Debug, JsonSchema)]
pub struct Tuple(
#[validate(range(max = 10))] u8,
#[validate(required)] Option<bool>,
);
#[test]
fn validate_tuple() -> TestResult {
test_default_generated_schema::<Tuple>("validate_tuple")
}
#[derive(Debug, JsonSchema)] #[derive(Debug, JsonSchema)]
pub struct NewType(#[validate(range(max = 10))] u8); pub struct NewType(#[validate(range(max = 10))] u8);

View file

@ -61,7 +61,14 @@ fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream {
let span = field.original.span(); let span = field.original.span();
let gen = quote!(gen); let gen = quote!(gen);
field.validation_attrs.apply_to_schema(if allow_ref { let schema_expr = if field.validation_attrs.required {
quote_spanned! {span=>
{
#type_def
<#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#gen)
}
}
} else if allow_ref {
quote_spanned! {span=> quote_spanned! {span=>
{ {
#type_def #type_def
@ -75,7 +82,8 @@ fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream {
<#ty as schemars::JsonSchema>::json_schema(#gen) <#ty as schemars::JsonSchema>::json_schema(#gen)
} }
} }
}) };
field.validation_attrs.apply_to_schema(schema_expr)
} }
pub fn type_for_field_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>) {
@ -375,17 +383,25 @@ fn expr_for_newtype_struct(field: &Field) -> TokenStream {
} }
fn expr_for_tuple_struct(fields: &[Field]) -> TokenStream { fn expr_for_tuple_struct(fields: &[Field]) -> TokenStream {
let (types, type_defs): (Vec<_>, Vec<_>) = fields let fields: Vec<_> = fields
.iter() .iter()
.filter(|f| !f.serde_attrs.skip_deserializing()) .filter(|f| !f.serde_attrs.skip_deserializing())
.enumerate() .map(|f| expr_for_field(f, true))
.map(|(i, f)| type_for_field_schema(f, i)) .collect();
.unzip(); let len = fields.len() as u32;
quote! { quote! {
{ schemars::schema::Schema::Object(
#(#type_defs)* schemars::schema::SchemaObject {
gen.subschema_for::<(#(#types),*)>() instance_type: Some(schemars::schema::InstanceType::Array.into()),
} array: Some(Box::new(schemars::schema::ArrayValidation {
items: Some(vec![#(#fields),*].into()),
max_items: Some(#len),
min_items: Some(#len),
..Default::default()
})),
..Default::default()
})
} }
} }