diff --git a/docs/1.1-attributes.md b/docs/1.1-attributes.md index 3cc38c43..64d4d148 100644 --- a/docs/1.1-attributes.md +++ b/docs/1.1-attributes.md @@ -38,6 +38,7 @@ TABLE OF CONTENTS - [`title` / `description`](#title-description) - [`example`](#example) - [`deprecated`](#deprecated) + - [`crate`](#crate) - [Doc Comments (`doc`)](#doc) @@ -182,6 +183,13 @@ Set on a container, variant or field to include the result of the given function Set the Rust built-in [`deprecated`](https://doc.rust-lang.org/edition-guide/rust-2018/the-compiler/an-attribute-for-deprecation.html) attribute on a struct, enum, field or variant to set the generated schema's `deprecated` keyword to `true`. +

+ +`#[schemars(crate = "other_crate::schemars")]` +

+ +Set the path to the schemars crate instance the generated code should depend on. This is mostly useful for other crates that depend on schemars in their macros. +

Doc Comments (`#[doc = "..."]`) diff --git a/schemars/tests/derive_crate.rs b/schemars/tests/derive_crate.rs new file mode 100644 index 00000000..1466f556 --- /dev/null +++ b/schemars/tests/derive_crate.rs @@ -0,0 +1,12 @@ +use ::schemars as not_schemars; + +#[allow(unused_imports)] +use std as schemars; + +#[derive(Debug, not_schemars::JsonSchema)] +#[schemars(crate = "not_schemars")] +pub struct Struct { + /// This is a document + foo: i32, + bar: bool, +} diff --git a/schemars_derive/src/attr/mod.rs b/schemars_derive/src/attr/mod.rs index 37919b3d..f2481498 100644 --- a/schemars_derive/src/attr/mod.rs +++ b/schemars_derive/src/attr/mod.rs @@ -17,6 +17,7 @@ pub struct Attrs { pub title: Option, pub description: Option, pub deprecated: bool, + pub crate_name: Option, pub examples: Vec, } @@ -118,6 +119,16 @@ impl Attrs { } } + Meta(NameValue(m)) if m.path.is_ident("crate") => { + if let Ok(p) = parse_lit_into_path(errors, attr_type, "crate", &m.lit) { + if self.crate_name.is_some() { + duplicate_error(m) + } else { + self.crate_name = Some(p) + } + } + } + _ if ignore_errors => {} Meta(meta_item) => { diff --git a/schemars_derive/src/lib.rs b/schemars_derive/src/lib.rs index d50a8903..887942b0 100644 --- a/schemars_derive/src/lib.rs +++ b/schemars_derive/src/lib.rs @@ -21,8 +21,6 @@ pub fn derive_json_schema_wrapper(input: proc_macro::TokenStream) -> proc_macro: } fn derive_json_schema(mut input: syn::DeriveInput) -> TokenStream { - add_trait_bounds(&mut input.generics); - if let Err(e) = attr::process_serde_attrs(&mut input) { return compile_error(&e); } @@ -32,40 +30,51 @@ fn derive_json_schema(mut input: syn::DeriveInput) -> TokenStream { Err(e) => return compile_error(&e), }; + let default_crate_name: syn::Path = parse_quote!(schemars); + let crate_name = cont + .attrs + .crate_name + .as_ref() + .unwrap_or(&default_crate_name); + + let mut gen = cont.generics.clone(); + + add_trait_bounds(&crate_name, &mut gen); + let type_name = &cont.ident; - let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl(); + let (impl_generics, ty_generics, where_clause) = gen.split_for_impl(); 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_schema(crate_name, transparent_field, 0); return quote! { #[automatically_derived] - impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause { + impl #impl_generics #crate_name::JsonSchema for #type_name #ty_generics #where_clause { #type_def fn is_referenceable() -> bool { - <#ty as schemars::JsonSchema>::is_referenceable() + <#ty as #crate_name::JsonSchema>::is_referenceable() } fn schema_name() -> std::string::String { - <#ty as schemars::JsonSchema>::schema_name() + <#ty as #crate_name::JsonSchema>::schema_name() } - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - <#ty as schemars::JsonSchema>::json_schema(gen) + fn json_schema(gen: &mut #crate_name::gen::SchemaGenerator) -> #crate_name::schema::Schema { + <#ty as #crate_name::JsonSchema>::json_schema(gen) } - fn json_schema_for_flatten(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - <#ty as schemars::JsonSchema>::json_schema_for_flatten(gen) + fn json_schema_for_flatten(gen: &mut #crate_name::gen::SchemaGenerator) -> #crate_name::schema::Schema { + <#ty as #crate_name::JsonSchema>::json_schema_for_flatten(gen) } fn add_schema_as_property( - gen: &mut schemars::gen::SchemaGenerator, - parent: &mut schemars::schema::SchemaObject, + gen: &mut #crate_name::gen::SchemaGenerator, + parent: &mut #crate_name::schema::SchemaObject, name: String, - metadata: Option, + metadata: Option<#crate_name::schema::Metadata>, required: bool, ) { - <#ty as schemars::JsonSchema>::add_schema_as_property(gen, parent, name, metadata, required) + <#ty as #crate_name::JsonSchema>::add_schema_as_property(gen, parent, name, metadata, required) } }; }; @@ -109,22 +118,24 @@ fn derive_json_schema(mut input: syn::DeriveInput) -> TokenStream { quote! { #[automatically_derived] #[allow(unused_braces)] - impl #impl_generics schemars::JsonSchema for #type_name #ty_generics #where_clause { + impl #impl_generics #crate_name::JsonSchema for #type_name #ty_generics #where_clause { fn schema_name() -> std::string::String { #schema_name } - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + fn json_schema(gen: &mut #crate_name::gen::SchemaGenerator) -> #crate_name::schema::Schema { #schema_expr } }; } } -fn add_trait_bounds(generics: &mut syn::Generics) { +fn add_trait_bounds(crate_name: &syn::Path, generics: &mut syn::Generics) { for param in &mut generics.params { if let syn::GenericParam::Type(ref mut type_param) = *param { - type_param.bounds.push(parse_quote!(schemars::JsonSchema)); + type_param + .bounds + .push(parse_quote!(#crate_name::JsonSchema)); } } } diff --git a/schemars_derive/src/metadata.rs b/schemars_derive/src/metadata.rs index 3f616eec..78f7c8aa 100644 --- a/schemars_derive/src/metadata.rs +++ b/schemars_derive/src/metadata.rs @@ -10,6 +10,7 @@ pub struct SchemaMetadata<'a> { pub deprecated: bool, pub read_only: bool, pub write_only: bool, + pub crate_name: &'a syn::Path, pub examples: &'a [syn::Path], pub default: Option, } @@ -17,12 +18,13 @@ pub struct SchemaMetadata<'a> { impl ToTokens for SchemaMetadata<'_> { fn to_tokens(&self, tokens: &mut TokenStream) { let setters = self.make_setters(); + let crate_name = self.crate_name; if setters.is_empty() { tokens.append(Ident::new("None", Span::call_site())) } else { tokens.extend(quote! { Some({ - let mut metadata = schemars::schema::Metadata::default(); + let mut metadata = #crate_name::schema::Metadata::default(); #(#setters)* metadata }) @@ -32,12 +34,15 @@ impl ToTokens for SchemaMetadata<'_> { } impl<'a> SchemaMetadata<'a> { - pub fn from_attrs(attrs: &'a Attrs) -> Self { + // Crate name is separate, because attrs could be for a variant + // instead of a container, and crate is only applicable to containers. + pub fn from_attrs(crate_name: &'a syn::Path, attrs: &'a Attrs) -> Self { SchemaMetadata { title: attrs.title.as_ref().and_then(none_if_empty), description: attrs.description.as_ref().and_then(none_if_empty), deprecated: attrs.deprecated, examples: &attrs.examples, + crate_name, read_only: false, write_only: false, default: None, @@ -55,6 +60,7 @@ impl<'a> SchemaMetadata<'a> { fn make_setters(&self) -> Vec { let mut setters = Vec::::new(); + let crate_name = self.crate_name; if let Some(title) = &self.title { setters.push(quote! { @@ -87,7 +93,7 @@ impl<'a> SchemaMetadata<'a> { if !self.examples.is_empty() { let examples = self.examples.iter().map(|eg| { quote! { - schemars::_serde_json::value::to_value(#eg()) + #crate_name::_serde_json::value::to_value(#eg()) } }); setters.push(quote! { @@ -97,7 +103,7 @@ impl<'a> SchemaMetadata<'a> { if let Some(default) = &self.default { setters.push(quote! { - metadata.default = #default.and_then(|d| schemars::_serde_json::value::to_value(d).ok()); + metadata.default = #default.and_then(|d| #crate_name::_serde_json::value::to_value(d).ok()); }); } diff --git a/schemars_derive/src/schema_exprs.rs b/schemars_derive/src/schema_exprs.rs index 6dc532db..7747ca47 100644 --- a/schemars_derive/src/schema_exprs.rs +++ b/schemars_derive/src/schema_exprs.rs @@ -5,20 +5,29 @@ use serde_derive_internals::attr::{self as serde_attr, Default as SerdeDefault, use syn::spanned::Spanned; pub fn expr_for_container(cont: &Container) -> TokenStream { + let default_crate_name: syn::Path = parse_quote!(schemars); + let crate_name = cont + .attrs + .crate_name + .as_ref() + .unwrap_or(&default_crate_name); + let schema_expr = match &cont.data { Data::Struct(Style::Unit, _) => expr_for_unit_struct(), - Data::Struct(Style::Newtype, fields) => expr_for_newtype_struct(&fields[0]), - Data::Struct(Style::Tuple, fields) => expr_for_tuple_struct(fields), - Data::Struct(Style::Struct, fields) => expr_for_struct(fields, Some(&cont.serde_attrs)), - Data::Enum(variants) => expr_for_enum(variants, &cont.serde_attrs), + Data::Struct(Style::Newtype, fields) => expr_for_newtype_struct(crate_name, &fields[0]), + Data::Struct(Style::Tuple, fields) => expr_for_tuple_struct(crate_name, fields), + Data::Struct(Style::Struct, fields) => { + expr_for_struct(crate_name, fields, Some(&cont.serde_attrs)) + } + Data::Enum(variants) => expr_for_enum(crate_name, variants, &cont.serde_attrs), }; - let doc_metadata = SchemaMetadata::from_attrs(&cont.attrs); + let doc_metadata = SchemaMetadata::from_attrs(crate_name, &cont.attrs); doc_metadata.apply_to_schema(schema_expr) } -fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream { - let (ty, type_def) = type_for_schema(field, 0); +fn expr_for_field(crate_name: &syn::Path, field: &Field, allow_ref: bool) -> TokenStream { + let (ty, type_def) = type_for_schema(crate_name, field, 0); let span = field.original.span(); if allow_ref { @@ -32,13 +41,17 @@ fn expr_for_field(field: &Field, allow_ref: bool) -> TokenStream { quote_spanned! {span=> { #type_def - <#ty as schemars::JsonSchema>::json_schema(gen) + <#ty as #crate_name::JsonSchema>::json_schema(gen) } } } } -pub fn type_for_schema(field: &Field, local_id: usize) -> (syn::Type, Option) { +pub fn type_for_schema( + crate_name: &syn::Path, + field: &Field, + local_id: usize, +) -> (syn::Type, Option) { match &field.attrs.with { None => (field.ty.to_owned(), None), Some(WithAttr::Type(ty)) => (ty.to_owned(), None), @@ -49,7 +62,7 @@ pub fn type_for_schema(field: &Field, local_id: usize) -> (syn::Type, Option struct #ty_name; - impl schemars::JsonSchema for #ty_name { + impl #crate_name::JsonSchema for #ty_name { fn is_referenceable() -> bool { false } @@ -58,7 +71,7 @@ pub fn type_for_schema(field: &Field, local_id: usize) -> (syn::Type, Option schemars::schema::Schema { + fn json_schema(gen: &mut #crate_name::gen::SchemaGenerator) -> #crate_name::schema::Schema { #fun(gen) } } @@ -69,29 +82,39 @@ pub fn type_for_schema(field: &Field, local_id: usize) -> (syn::Type, Option TokenStream { +fn expr_for_enum( + crate_name: &syn::Path, + variants: &[Variant], + cattrs: &serde_attr::Container, +) -> TokenStream { let variants = variants .iter() .filter(|v| !v.serde_attrs.skip_deserializing()); match cattrs.tag() { - TagType::External => expr_for_external_tagged_enum(variants), - TagType::None => expr_for_untagged_enum(variants), - TagType::Internal { tag } => expr_for_internal_tagged_enum(variants, tag), - TagType::Adjacent { tag, content } => expr_for_adjacent_tagged_enum(variants, tag, content), + TagType::External => expr_for_external_tagged_enum(crate_name, variants), + TagType::None => expr_for_untagged_enum(crate_name, variants), + TagType::Internal { tag } => expr_for_internal_tagged_enum(crate_name, variants, tag), + TagType::Adjacent { tag, content } => { + expr_for_adjacent_tagged_enum(crate_name, variants, tag, content) + } } } fn expr_for_external_tagged_enum<'a>( + crate_name: &syn::Path, variants: impl Iterator>, ) -> TokenStream { let (unit_variants, complex_variants): (Vec<_>, Vec<_>) = variants.partition(|v| v.is_unit() && v.attrs.with.is_none()); let unit_names = unit_variants.iter().map(|v| v.name()); - let unit_schema = schema_object(quote! { - instance_type: Some(schemars::schema::InstanceType::String.into()), - enum_values: Some(vec![#(#unit_names.into()),*]), - }); + let unit_schema = schema_object( + crate_name, + quote! { + instance_type: Some(#crate_name::schema::InstanceType::String.into()), + enum_values: Some(vec![#(#unit_names.into()),*]), + }, + ); if complex_variants.is_empty() { return unit_schema; @@ -104,66 +127,79 @@ fn expr_for_external_tagged_enum<'a>( schemas.extend(complex_variants.into_iter().map(|variant| { let name = variant.name(); - let sub_schema = expr_for_untagged_enum_variant(variant); - let schema_expr = schema_object(quote! { - instance_type: Some(schemars::schema::InstanceType::Object.into()), - object: Some(Box::new(schemars::schema::ObjectValidation { - properties: { - let mut props = schemars::Map::new(); - props.insert(#name.to_owned(), #sub_schema); - props - }, - required: { - let mut required = schemars::Set::new(); - required.insert(#name.to_owned()); - required - }, - ..Default::default() - })), - }); - let doc_metadata = SchemaMetadata::from_attrs(&variant.attrs); + let sub_schema = expr_for_untagged_enum_variant(crate_name, variant); + let schema_expr = schema_object( + crate_name, + quote! { + instance_type: Some(#crate_name::schema::InstanceType::Object.into()), + object: Some(Box::new(#crate_name::schema::ObjectValidation { + properties: { + let mut props = #crate_name::Map::new(); + props.insert(#name.to_owned(), #sub_schema); + props + }, + required: { + let mut required = #crate_name::Set::new(); + required.insert(#name.to_owned()); + required + }, + ..Default::default() + })), + }, + ); + let doc_metadata = SchemaMetadata::from_attrs(crate_name, &variant.attrs); doc_metadata.apply_to_schema(schema_expr) })); - schema_object(quote! { - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(vec![#(#schemas),*]), - ..Default::default() - })), - }) + schema_object( + crate_name, + quote! { + subschemas: Some(Box::new(#crate_name::schema::SubschemaValidation { + any_of: Some(vec![#(#schemas),*]), + ..Default::default() + })), + }, + ) } fn expr_for_internal_tagged_enum<'a>( + crate_name: &syn::Path, variants: impl Iterator>, tag_name: &str, ) -> TokenStream { let variant_schemas = variants.map(|variant| { let name = variant.name(); - let type_schema = schema_object(quote! { - instance_type: Some(schemars::schema::InstanceType::String.into()), - enum_values: Some(vec![#name.into()]), - }); + let type_schema = schema_object( + crate_name, + quote! { + instance_type: Some(#crate_name::schema::InstanceType::String.into()), + enum_values: Some(vec![#name.into()]), + }, + ); - let tag_schema = schema_object(quote! { - instance_type: Some(schemars::schema::InstanceType::Object.into()), - object: Some(Box::new(schemars::schema::ObjectValidation { - properties: { - let mut props = schemars::Map::new(); - props.insert(#tag_name.to_owned(), #type_schema); - props - }, - required: { - let mut required = schemars::Set::new(); - required.insert(#tag_name.to_owned()); - required - }, - ..Default::default() - })), - }); - let doc_metadata = SchemaMetadata::from_attrs(&variant.attrs); + let tag_schema = schema_object( + crate_name, + quote! { + instance_type: Some(#crate_name::schema::InstanceType::Object.into()), + object: Some(Box::new(#crate_name::schema::ObjectValidation { + properties: { + let mut props = #crate_name::Map::new(); + props.insert(#tag_name.to_owned(), #type_schema); + props + }, + required: { + let mut required = #crate_name::Set::new(); + required.insert(#tag_name.to_owned()); + required + }, + ..Default::default() + })), + }, + ); + let doc_metadata = SchemaMetadata::from_attrs(crate_name, &variant.attrs); let tag_schema = doc_metadata.apply_to_schema(tag_schema); - match expr_for_untagged_enum_variant_for_flatten(&variant) { + match expr_for_untagged_enum_variant_for_flatten(crate_name, &variant) { Some(variant_schema) => quote! { #tag_schema.flatten(#variant_schema) }, @@ -171,30 +207,40 @@ fn expr_for_internal_tagged_enum<'a>( } }); - schema_object(quote! { - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(vec![#(#variant_schemas),*]), - ..Default::default() - })), - }) + schema_object( + crate_name, + quote! { + subschemas: Some(Box::new(#crate_name::schema::SubschemaValidation { + any_of: Some(vec![#(#variant_schemas),*]), + ..Default::default() + })), + }, + ) } -fn expr_for_untagged_enum<'a>(variants: impl Iterator>) -> TokenStream { +fn expr_for_untagged_enum<'a>( + crate_name: &syn::Path, + variants: impl Iterator>, +) -> TokenStream { let schemas = variants.map(|variant| { - let schema_expr = expr_for_untagged_enum_variant(variant); - let doc_metadata = SchemaMetadata::from_attrs(&variant.attrs); + let schema_expr = expr_for_untagged_enum_variant(crate_name, variant); + let doc_metadata = SchemaMetadata::from_attrs(crate_name, &variant.attrs); doc_metadata.apply_to_schema(schema_expr) }); - schema_object(quote! { - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(vec![#(#schemas),*]), - ..Default::default() - })), - }) + schema_object( + crate_name, + quote! { + subschemas: Some(Box::new(#crate_name::schema::SubschemaValidation { + any_of: Some(vec![#(#schemas),*]), + ..Default::default() + })), + }, + ) } fn expr_for_adjacent_tagged_enum<'a>( + crate_name: &syn::Path, variants: impl Iterator>, tag_name: &str, content_name: &str, @@ -203,7 +249,7 @@ fn expr_for_adjacent_tagged_enum<'a>( let content_schema = if variant.is_unit() && variant.attrs.with.is_none() { None } else { - Some(expr_for_untagged_enum_variant(variant)) + Some(expr_for_untagged_enum_variant(crate_name, variant)) }; let (add_content_to_props, add_content_to_required) = content_schema @@ -216,43 +262,52 @@ fn expr_for_adjacent_tagged_enum<'a>( .unwrap_or_default(); let name = variant.name(); - let tag_schema = schema_object(quote! { - instance_type: Some(schemars::schema::InstanceType::String.into()), - enum_values: Some(vec![#name.into()]), - }); + let tag_schema = schema_object( + crate_name, + quote! { + instance_type: Some(#crate_name::schema::InstanceType::String.into()), + enum_values: Some(vec![#name.into()]), + }, + ); - let outer_schema = schema_object(quote! { - instance_type: Some(schemars::schema::InstanceType::Object.into()), - object: Some(Box::new(schemars::schema::ObjectValidation { - properties: { - let mut props = schemars::Map::new(); - props.insert(#tag_name.to_owned(), #tag_schema); - #add_content_to_props - props - }, - required: { - let mut required = schemars::Set::new(); - required.insert(#tag_name.to_owned()); - #add_content_to_required - required - }, - ..Default::default() - })), - }); + let outer_schema = schema_object( + crate_name, + quote! { + instance_type: Some(#crate_name::schema::InstanceType::Object.into()), + object: Some(Box::new(#crate_name::schema::ObjectValidation { + properties: { + let mut props = #crate_name::Map::new(); + props.insert(#tag_name.to_owned(), #tag_schema); + #add_content_to_props + props + }, + required: { + let mut required = #crate_name::Set::new(); + required.insert(#tag_name.to_owned()); + #add_content_to_required + required + }, + ..Default::default() + })), + }, + ); - let doc_metadata = SchemaMetadata::from_attrs(&variant.attrs); + let doc_metadata = SchemaMetadata::from_attrs(crate_name, &variant.attrs); doc_metadata.apply_to_schema(outer_schema) }); - schema_object(quote! { - subschemas: Some(Box::new(schemars::schema::SubschemaValidation { - any_of: Some(vec![#(#schemas),*]), - ..Default::default() - })), - }) + schema_object( + crate_name, + quote! { + subschemas: Some(Box::new(#crate_name::schema::SubschemaValidation { + any_of: Some(vec![#(#schemas),*]), + ..Default::default() + })), + }, + ) } -fn expr_for_untagged_enum_variant(variant: &Variant) -> TokenStream { +fn expr_for_untagged_enum_variant(crate_name: &syn::Path, variant: &Variant) -> TokenStream { if let Some(WithAttr::Type(with)) = &variant.attrs.with { return quote_spanned! {variant.original.span()=> gen.subschema_for::<#with>() @@ -261,13 +316,16 @@ fn expr_for_untagged_enum_variant(variant: &Variant) -> TokenStream { match variant.style { Style::Unit => expr_for_unit_struct(), - Style::Newtype => expr_for_field(&variant.fields[0], true), - Style::Tuple => expr_for_tuple_struct(&variant.fields), - Style::Struct => expr_for_struct(&variant.fields, None), + Style::Newtype => expr_for_field(crate_name, &variant.fields[0], true), + Style::Tuple => expr_for_tuple_struct(crate_name, &variant.fields), + Style::Struct => expr_for_struct(crate_name, &variant.fields, None), } } -fn expr_for_untagged_enum_variant_for_flatten(variant: &Variant) -> Option { +fn expr_for_untagged_enum_variant_for_flatten( + crate_name: &syn::Path, + variant: &Variant, +) -> Option { if let Some(WithAttr::Type(with)) = &variant.attrs.with { return Some(quote_spanned! {variant.original.span()=> <#with>::json_schema(gen) @@ -276,9 +334,9 @@ fn expr_for_untagged_enum_variant_for_flatten(variant: &Variant) -> Option return None, - Style::Newtype => expr_for_field(&variant.fields[0], false), - Style::Tuple => expr_for_tuple_struct(&variant.fields), - Style::Struct => expr_for_struct(&variant.fields, None), + Style::Newtype => expr_for_field(crate_name, &variant.fields[0], false), + Style::Tuple => expr_for_tuple_struct(crate_name, &variant.fields), + Style::Struct => expr_for_struct(crate_name, &variant.fields, None), }) } @@ -288,16 +346,16 @@ fn expr_for_unit_struct() -> TokenStream { } } -fn expr_for_newtype_struct(field: &Field) -> TokenStream { - expr_for_field(field, true) +fn expr_for_newtype_struct(crate_name: &syn::Path, field: &Field) -> TokenStream { + expr_for_field(crate_name, field, true) } -fn expr_for_tuple_struct(fields: &[Field]) -> TokenStream { +fn expr_for_tuple_struct(crate_name: &syn::Path, fields: &[Field]) -> TokenStream { let (types, type_defs): (Vec<_>, Vec<_>) = fields .iter() .filter(|f| !f.serde_attrs.skip_deserializing()) .enumerate() - .map(|(i, f)| type_for_schema(f, i)) + .map(|(i, f)| type_for_schema(crate_name, f, i)) .unzip(); quote! { { @@ -307,7 +365,11 @@ fn expr_for_tuple_struct(fields: &[Field]) -> TokenStream { } } -fn expr_for_struct(fields: &[Field], cattrs: Option<&serde_attr::Container>) -> TokenStream { +fn expr_for_struct( + crate_name: &syn::Path, + fields: &[Field], + cattrs: Option<&serde_attr::Container>, +) -> TokenStream { let (flattened_fields, property_fields): (Vec<_>, Vec<_>) = fields .iter() .filter(|f| !f.serde_attrs.skip_deserializing() || !f.serde_attrs.skip_serializing()) @@ -334,16 +396,16 @@ fn expr_for_struct(fields: &[Field], cattrs: Option<&serde_attr::Container>) -> read_only: field.serde_attrs.skip_deserializing(), write_only: field.serde_attrs.skip_serializing(), default, - ..SchemaMetadata::from_attrs(&field.attrs) + ..SchemaMetadata::from_attrs(crate_name, &field.attrs) }; - let (ty, type_def) = type_for_schema(field, type_defs.len()); + let (ty, type_def) = type_for_schema(crate_name, field, type_defs.len()); if let Some(type_def) = type_def { type_defs.push(type_def); } quote_spanned! {ty.span()=> - <#ty as schemars::JsonSchema>::add_schema_as_property(gen, &mut schema_object, #name.to_owned(), #metadata, #required); + <#ty as #crate_name::JsonSchema>::add_schema_as_property(gen, &mut schema_object, #name.to_owned(), #metadata, #required); } }).collect(); @@ -351,13 +413,13 @@ fn expr_for_struct(fields: &[Field], cattrs: Option<&serde_attr::Container>) -> let flattens: Vec<_> = flattened_fields .into_iter() .map(|field| { - let (ty, type_def) = type_for_schema(field, type_defs.len()); + let (ty, type_def) = type_for_schema(crate_name, field, type_defs.len()); if let Some(type_def) = type_def { type_defs.push(type_def); } quote_spanned! {ty.span()=> - .flatten(<#ty as schemars::JsonSchema>::json_schema_for_flatten(gen)) + .flatten(<#ty as #crate_name::JsonSchema>::json_schema_for_flatten(gen)) } }) .collect(); @@ -375,13 +437,13 @@ fn expr_for_struct(fields: &[Field], cattrs: Option<&serde_attr::Container>) -> { #(#type_defs)* #set_container_default - let mut schema_object = schemars::schema::SchemaObject { - instance_type: Some(schemars::schema::InstanceType::Object.into()), + let mut schema_object = #crate_name::schema::SchemaObject { + instance_type: Some(#crate_name::schema::InstanceType::Object.into()), ..Default::default() }; #set_additional_properties #(#properties)* - schemars::schema::Schema::Object(schema_object) + #crate_name::schema::Schema::Object(schema_object) #(#flattens)* } } @@ -442,10 +504,10 @@ fn field_default_expr(field: &Field, container_has_default: bool) -> Option TokenStream { +fn schema_object(crate_name: &syn::Path, properties: TokenStream) -> TokenStream { quote! { - schemars::schema::Schema::Object( - schemars::schema::SchemaObject { + #crate_name::schema::Schema::Object( + #crate_name::schema::SchemaObject { #properties ..Default::default() })