Handle required flattened Option fields
This commit is contained in:
parent
b68132f17d
commit
1a2dafc1a5
5 changed files with 37 additions and 18 deletions
|
@ -4,9 +4,14 @@ use crate::schema::{Metadata, Schema, SchemaObject};
|
||||||
use crate::JsonSchema;
|
use crate::JsonSchema;
|
||||||
|
|
||||||
// Helper for generating schemas for flattened `Option` fields.
|
// Helper for generating schemas for flattened `Option` fields.
|
||||||
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(gen: &mut SchemaGenerator) -> Schema {
|
pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(
|
||||||
|
gen: &mut SchemaGenerator,
|
||||||
|
required: Option<bool>,
|
||||||
|
) -> Schema {
|
||||||
let mut schema = T::_schemars_private_non_optional_json_schema(gen);
|
let mut schema = T::_schemars_private_non_optional_json_schema(gen);
|
||||||
if T::_schemars_private_is_option() {
|
|
||||||
|
let required = required.unwrap_or_else(|| !T::_schemars_private_is_option());
|
||||||
|
if !required {
|
||||||
if let Schema::Object(SchemaObject {
|
if let Schema::Object(SchemaObject {
|
||||||
object: Some(ref mut object_validation),
|
object: Some(ref mut object_validation),
|
||||||
..
|
..
|
||||||
|
@ -15,6 +20,7 @@ pub fn json_schema_for_flatten<T: ?Sized + JsonSchema>(gen: &mut SchemaGenerator
|
||||||
object_validation.required.clear();
|
object_validation.required.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
schema
|
schema
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +34,13 @@ pub fn add_schema_as_property<T: ?Sized + JsonSchema>(
|
||||||
) {
|
) {
|
||||||
let is_type_option = T::_schemars_private_is_option();
|
let is_type_option = T::_schemars_private_is_option();
|
||||||
let required = required.unwrap_or(!is_type_option);
|
let required = required.unwrap_or(!is_type_option);
|
||||||
|
|
||||||
let mut schema = if required && is_type_option {
|
let mut schema = if required && is_type_option {
|
||||||
T::_schemars_private_non_optional_json_schema(gen)
|
T::_schemars_private_non_optional_json_schema(gen)
|
||||||
} else {
|
} else {
|
||||||
gen.subschema_for::<T>()
|
gen.subschema_for::<T>()
|
||||||
};
|
};
|
||||||
|
|
||||||
schema = apply_metadata(schema, metadata);
|
schema = apply_metadata(schema, metadata);
|
||||||
|
|
||||||
let object = parent.object();
|
let object = parent.object();
|
||||||
|
|
|
@ -14,7 +14,8 @@
|
||||||
"regex_str1",
|
"regex_str1",
|
||||||
"regex_str2",
|
"regex_str2",
|
||||||
"required_option",
|
"required_option",
|
||||||
"tel"
|
"tel",
|
||||||
|
"x"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"min_max": {
|
"min_max": {
|
||||||
|
@ -76,6 +77,10 @@
|
||||||
},
|
},
|
||||||
"required_option": {
|
"required_option": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"x": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,14 @@ pub struct Struct {
|
||||||
map_contains: HashMap<String, ()>,
|
map_contains: HashMap<String, ()>,
|
||||||
#[validate(required)]
|
#[validate(required)]
|
||||||
required_option: Option<bool>,
|
required_option: Option<bool>,
|
||||||
|
#[validate(required)]
|
||||||
|
#[serde(flatten)]
|
||||||
|
required_flattened: Option<Inner>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, JsonSchema)]
|
||||||
|
pub struct Inner {
|
||||||
|
x: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -120,17 +120,9 @@ impl ValidationAttrs {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validation_statements(&self, field_name: &str) -> TokenStream {
|
pub fn validation_statements(&self, field_name: &str) -> Option<TokenStream> {
|
||||||
// Assume that the result will be interpolated in a context with the local variable
|
// Assume that the result will be interpolated in a context with the local variable
|
||||||
// `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();
|
|
||||||
|
|
||||||
// if self.required {
|
|
||||||
// statements.push(quote! {
|
|
||||||
// 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();
|
||||||
let mut object_validation = Vec::new();
|
let mut object_validation = Vec::new();
|
||||||
|
@ -210,7 +202,7 @@ impl ValidationAttrs {
|
||||||
|| string_validation.is_some()
|
|| string_validation.is_some()
|
||||||
|| format.is_some()
|
|| format.is_some()
|
||||||
{
|
{
|
||||||
statements.push(quote! {
|
Some(quote! {
|
||||||
if let Some(schemars::schema::Schema::Object(prop_schema_object)) = schema_object
|
if let Some(schemars::schema::Schema::Object(prop_schema_object)) = schema_object
|
||||||
.object
|
.object
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
@ -222,10 +214,10 @@ impl ValidationAttrs {
|
||||||
#string_validation
|
#string_validation
|
||||||
#format
|
#format
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
statements.into_iter().collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,9 +449,15 @@ fn expr_for_struct(
|
||||||
type_defs.push(type_def);
|
type_defs.push(type_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
let gen = quote!(gen);
|
let required = if field.validation_attrs.required {
|
||||||
|
quote!(Some(true))
|
||||||
|
} else {
|
||||||
|
quote!(None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let args = quote!(gen, #required);
|
||||||
quote_spanned! {ty.span()=>
|
quote_spanned! {ty.span()=>
|
||||||
.flatten(schemars::_private::json_schema_for_flatten::<#ty>(#gen))
|
.flatten(schemars::_private::json_schema_for_flatten::<#ty>(#args))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue