Set "default" on generated schemas (#6)

This commit is contained in:
Graham Esau 2019-12-08 15:17:08 +00:00
parent 81eb53b590
commit 7e23e2ad7a
7 changed files with 69 additions and 12 deletions

View file

@ -281,11 +281,33 @@ fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream
.filter(|f| !f.attrs.skip_deserializing() || !f.attrs.skip_serializing())
.partition(|f| f.attrs.flatten());
let container_has_default = has_default(cattrs.default());
let set_container_default = match cattrs.default() {
SerdeDefault::None => None,
SerdeDefault::Default => Some(quote!(let cdefault = Self::default();)),
SerdeDefault::Path(path) => Some(quote!(let cdefault = #path();)),
};
let mut required = Vec::new();
let recurse = nested.iter().map(|field| {
let name = field.attrs.name().deserialize_name();
if !container_has_default && !has_default(field.attrs.default()) {
let ty = field.ty;
// TODO respect serialize_with on field
let default = match field.attrs.default() {
SerdeDefault::None if set_container_default.is_some() => {
let field_ident = field
.original
.ident
.as_ref()
.expect("This is not a tuple struct, so field should be named");
Some(quote!(cdefault.#field_ident))
}
SerdeDefault::None => None,
SerdeDefault::Default => Some(quote!(<#ty>::default())),
SerdeDefault::Path(path) => Some(quote!(#path())),
};
if default.is_none() {
required.push(name.clone());
}
@ -298,6 +320,7 @@ fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream
let metadata = SchemaMetadata {
read_only: field.attrs.skip_deserializing(),
write_only: field.attrs.skip_serializing(),
default,
..get_metadata_from_docs(&field.original.attrs)
};
let schema_expr = set_metadata_on_schema(schema_expr, &metadata);
@ -332,14 +355,10 @@ fn schema_for_struct(fields: &[Field], cattrs: &attr::Container) -> TokenStream
});
quote! {
#schema #(#flattens)*
}
}
fn has_default(d: &SerdeDefault) -> bool {
match d {
SerdeDefault::None => false,
_ => true,
{
#set_container_default
#schema #(#flattens)*
}
}
}

View file

@ -2,12 +2,13 @@ use crate::doc_attrs;
use proc_macro2::TokenStream;
use syn::Attribute;
#[derive(Debug, Clone, PartialEq, Default)]
#[derive(Debug, Clone, Default)]
pub struct SchemaMetadata {
pub title: Option<String>,
pub description: Option<String>,
pub read_only: bool,
pub write_only: bool,
pub default: Option<TokenStream>,
}
pub fn set_metadata_on_schema_from_docs(
@ -40,6 +41,7 @@ pub fn set_metadata_on_schema(schema_expr: TokenStream, metadata: &SchemaMetadat
metadata.description = Some(#description.to_owned());
})
}
if metadata.read_only {
setters.push(quote! {
metadata.read_only = true;
@ -51,6 +53,15 @@ pub fn set_metadata_on_schema(schema_expr: TokenStream, metadata: &SchemaMetadat
})
}
if let Some(default) = &metadata.default {
setters.push(quote! {
metadata.default = match serde_json::json!(#default) {
serde_json::value::Value::Null => None,
d => Some(d),
};
})
}
if setters.is_empty() {
return schema_expr;
}