Add transform = ...
attribute (#312)
This allows running arbitrary transforms on generated schemas when deriving `JsonSchema`
This commit is contained in:
parent
29067a0331
commit
14b06e71ba
10 changed files with 173 additions and 10 deletions
|
@ -27,6 +27,7 @@ pub struct Attrs {
|
|||
pub crate_name: Option<syn::Path>,
|
||||
pub is_renamed: bool,
|
||||
pub extensions: Vec<(String, TokenStream)>,
|
||||
pub transforms: Vec<syn::Expr>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -70,6 +71,7 @@ impl Attrs {
|
|||
deprecated: self.deprecated,
|
||||
examples: &self.examples,
|
||||
extensions: &self.extensions,
|
||||
transforms: &self.transforms,
|
||||
read_only: false,
|
||||
write_only: false,
|
||||
default: None,
|
||||
|
@ -164,6 +166,25 @@ impl Attrs {
|
|||
}
|
||||
}
|
||||
|
||||
Meta::NameValue(m) if m.path.is_ident("transform") && attr_type == "schemars" => {
|
||||
if let syn::Expr::Lit(syn::ExprLit {
|
||||
lit: syn::Lit::Str(lit_str),
|
||||
..
|
||||
}) = &m.value
|
||||
{
|
||||
if parse_lit_str::<syn::Expr>(lit_str).is_ok() {
|
||||
errors.error_spanned_by(
|
||||
&m.value,
|
||||
format!(
|
||||
"Expected a `fn(&mut Schema)` or other value implementing `schemars::transform::Transform`, found `&str`.\nDid you mean `[schemars(transform = {})]`?",
|
||||
lit_str.value()
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
self.transforms.push(m.value.clone());
|
||||
}
|
||||
|
||||
Meta::List(m) if m.path.is_ident("extend") && attr_type == "schemars" => {
|
||||
let parser =
|
||||
syn::punctuated::Punctuated::<Extension, Token![,]>::parse_terminated;
|
||||
|
@ -224,7 +245,8 @@ impl Attrs {
|
|||
crate_name: None,
|
||||
is_renamed: _,
|
||||
extensions,
|
||||
} if examples.is_empty() && extensions.is_empty())
|
||||
transforms
|
||||
} if examples.is_empty() && extensions.is_empty() && transforms.is_empty())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use syn::spanned::Spanned;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SchemaMetadata<'a> {
|
||||
|
@ -10,6 +11,7 @@ pub struct SchemaMetadata<'a> {
|
|||
pub examples: &'a [syn::Path],
|
||||
pub default: Option<TokenStream>,
|
||||
pub extensions: &'a [(String, TokenStream)],
|
||||
pub transforms: &'a [syn::Expr],
|
||||
}
|
||||
|
||||
impl<'a> SchemaMetadata<'a> {
|
||||
|
@ -23,6 +25,18 @@ impl<'a> SchemaMetadata<'a> {
|
|||
schema
|
||||
}}
|
||||
}
|
||||
if !self.transforms.is_empty() {
|
||||
let apply_transforms = self.transforms.iter().map(|t| {
|
||||
quote_spanned! {t.span()=>
|
||||
schemars::transform::Transform::transform(&mut #t, &mut schema);
|
||||
}
|
||||
});
|
||||
*schema_expr = quote! {{
|
||||
let mut schema = #schema_expr;
|
||||
#(#apply_transforms)*
|
||||
schema
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
fn make_setters(&self) -> Vec<TokenStream> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue