diff --git a/docs/0-migrating.md b/docs/0-migrating.md index be79b360..fba59ddf 100644 --- a/docs/0-migrating.md +++ b/docs/0-migrating.md @@ -126,12 +126,12 @@ use schemars::Schema; pub struct MyTransform; impl Transform for MyTransform { - fn transform(&mut self, schema: &mut Schema) { + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { // First, make our change to this schema schema.insert("my_property".to_string(), serde_json::json!("hello world")); // Then apply the transform to any subschemas - transform_subschemas(self, schema); + transform_subschemas(self, schema, generator); } } @@ -139,32 +139,34 @@ let mut schema = schemars::schema_for!(str); MyTransform.transform(&mut schema); ``` -Also, since `Transform` is now implemented for functions that take a single `&mut Schema` argument, you could also define it as a function instead of a struct: +Also, since `Transform` is now implemented for functions that take a `&mut Schema` and `&mut SchemaGenerator` arguments, you could also define it as a function instead of a struct: ```rust -fn my_transform(schema: &mut Schema) { +fn my_transform(schema: &mut Schema, generator: &mut SchemaGenerator) { // First, make our change to this schema schema.insert("my_property".to_string(), serde_json::json!("hello world")); // Then apply the transform to any subschemas - transform_subschemas(&mut my_transform, schema); + transform_subschemas(&mut my_transform, schema, generator); } let mut schema = schemars::schema_for!(str); -my_transform(&mut schema); +let mut generator = SchemaGenerator::default(); +my_transform(&mut schema, &mut generator); // Or equivalently: -// my_transform.transform(&mut schema); +// my_transform.transform(&mut schema, &mut generator); ``` Finally, you can also use the `RecursiveTransform` newtype to convert a non-recursive `Transform` (i.e. one that does not transform subschemas) into a recursive one, like so: ```rust -fn my_transform2(schema: &mut Schema) { +fn my_transform2(schema: &mut Schema, _generator: &mut SchemaGenerator) { schema.insert("my_property".to_string(), serde_json::json!("hello world")); } let mut schema = schemars::schema_for!(str); -RecursiveTransform(my_transform2).transform(&mut schema); +let mut generator = SchemaGenerator::default(); +RecursiveTransform(my_transform2).transform(&mut schema, &mut generator); ``` ## Changes to `#[validate(...)]` attributes diff --git a/docs/_includes/attributes.md b/docs/_includes/attributes.md index 1497b0f7..2391f0c9 100644 --- a/docs/_includes/attributes.md +++ b/docs/_includes/attributes.md @@ -348,10 +348,10 @@ struct Struct; Set on a container, variant or field to run a `schemars::transform::Transform` against the generated schema. This can be specified multiple times to run multiple transforms. -The `Transform` trait is implemented on functions with the signature `fn(&mut Schema) -> ()`, allowing you to do this: +The `Transform` trait is implemented on functions with the signature `fn(&mut Schema, &mut SchemaGenerator) -> ()`, allowing you to do this: ```rust -fn my_transform(schema: &mut Schema) { +fn my_transform(schema: &mut Schema, generator: &mut SchemaGenerator) { todo!() } @@ -360,6 +360,8 @@ fn my_transform(schema: &mut Schema) { struct Struct; ``` +The transform function can use the `SchemaGenerator` to inject schemas in the `$defs` section. +

Doc Comments (`#[doc = "..."]`) diff --git a/docs/_includes/examples/schemars_attrs.rs b/docs/_includes/examples/schemars_attrs.rs index 21c3bdcf..ca6d7026 100644 --- a/docs/_includes/examples/schemars_attrs.rs +++ b/docs/_includes/examples/schemars_attrs.rs @@ -24,7 +24,7 @@ pub enum MyEnum { }, } -fn remove_format(schema: &mut Schema) { +fn remove_format(schema: &mut Schema, _generator: &mut SchemaGenerator) { schema.remove("format"); } diff --git a/schemars/examples/schemars_attrs.rs b/schemars/examples/schemars_attrs.rs index 21c3bdcf..209a9172 100644 --- a/schemars/examples/schemars_attrs.rs +++ b/schemars/examples/schemars_attrs.rs @@ -1,4 +1,4 @@ -use schemars::{schema_for, JsonSchema, Schema}; +use schemars::{schema_for, JsonSchema, Schema, SchemaGenerator}; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize, JsonSchema)] @@ -24,7 +24,7 @@ pub enum MyEnum { }, } -fn remove_format(schema: &mut Schema) { +fn remove_format(schema: &mut Schema, _generator: &mut SchemaGenerator) { schema.remove("format"); } diff --git a/schemars/src/_private/mod.rs b/schemars/src/_private/mod.rs index aa5c6fe5..9088c19d 100644 --- a/schemars/src/_private/mod.rs +++ b/schemars/src/_private/mod.rs @@ -29,7 +29,7 @@ pub fn json_schema_for_internally_tagged_enum_newtype_variant( // Always allow aditional/unevaluated properties, because the outer struct determines // whether it denies unknown fields. - AllowUnknownProperties::default().transform(&mut schema); + AllowUnknownProperties::default().transform(&mut schema, generator); schema } @@ -69,7 +69,7 @@ struct AllowUnknownProperties { } impl Transform for AllowUnknownProperties { - fn transform(&mut self, schema: &mut Schema) { + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { if schema.get("additionalProperties").and_then(Value::as_bool) == Some(false) { schema.remove("additionalProperties"); self.did_modify = true; @@ -79,7 +79,7 @@ impl Transform for AllowUnknownProperties { self.did_modify = true; } - transform_immediate_subschemas(self, schema); + transform_immediate_subschemas(self, schema, generator); } } diff --git a/schemars/src/generate.rs b/schemars/src/generate.rs index 498d3b47..785e853a 100644 --- a/schemars/src/generate.rs +++ b/schemars/src/generate.rs @@ -368,6 +368,21 @@ impl SchemaGenerator { self.settings.transforms.iter_mut().map(Box::as_mut) } + /// Returns an iterator over the [transforms](SchemaSettings::transforms) being used by this + /// `SchemaGenerator`. + fn take_transforms(&mut self) -> Vec> { + core::mem::take(&mut self.settings.transforms) + } + + /// Returns an iterator over the [transforms](SchemaSettings::transforms) being used by this + /// `SchemaGenerator`. + fn set_transforms( + &mut self, + transforms: Vec>, + ) -> Vec> { + core::mem::replace(&mut self.settings.transforms, transforms) + } + /// Generates a JSON Schema for the type `T`. /// /// If `T`'s schema depends on any [non-inlined](JsonSchema::always_inline_schema) schemas, then @@ -538,9 +553,11 @@ impl SchemaGenerator { } fn apply_transforms(&mut self, schema: &mut Schema) { - for transform in self.transforms_mut() { - transform.transform(schema); + let mut transforms = self.take_transforms(); + for transform in &mut transforms { + transform.transform(schema, self); } + self.set_transforms(transforms); } /// Returns `self.settings.definitions_path` as a plain JSON pointer to the definitions object, @@ -606,7 +623,7 @@ fn json_pointer_mut<'a>( /// struct MyTransform; /// /// impl Transform for MyTransform { -/// fn transform(&mut self, schema: &mut schemars::Schema) { +/// fn transform(&mut self, schema: &mut schemars::Schema, generator: &mut schemars::SchemaGenerator) { /// todo!() /// } /// } diff --git a/schemars/src/transform.rs b/schemars/src/transform.rs index 7d24b5d6..68eaa35f 100644 --- a/schemars/src/transform.rs +++ b/schemars/src/transform.rs @@ -13,27 +13,29 @@ To make a transform recursive (i.e. apply it to subschemas), you have two option To add a custom property to all object schemas: ``` -# use schemars::{Schema, json_schema}; +# use schemars::{Schema, json_schema, SchemaGenerator}; use schemars::transform::{Transform, transform_subschemas}; pub struct MyTransform; impl Transform for MyTransform { - fn transform(&mut self, schema: &mut Schema) { + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { // First, make our change to this schema schema.insert("my_property".to_string(), "hello world".into()); // Then apply the transform to any subschemas - transform_subschemas(self, schema); + transform_subschemas(self, schema, generator); } } +let mut generator = SchemaGenerator::default(); + let mut schema = json_schema!({ "type": "array", "items": {} }); -MyTransform.transform(&mut schema); +MyTransform.transform(&mut schema, &mut generator); assert_eq!( schema, @@ -49,21 +51,23 @@ assert_eq!( The same example with a `fn` transform: ``` -# use schemars::{Schema, json_schema}; +# use schemars::{Schema, json_schema, SchemaGenerator}; use schemars::transform::transform_subschemas; -fn add_property(schema: &mut Schema) { +fn add_property(schema: &mut Schema, generator: &mut SchemaGenerator) { schema.insert("my_property".to_string(), "hello world".into()); - transform_subschemas(&mut add_property, schema) + transform_subschemas(&mut add_property, schema, generator) } +let mut generator = SchemaGenerator::default(); + let mut schema = json_schema!({ "type": "array", "items": {} }); -add_property(&mut schema); +add_property(&mut schema, &mut generator); assert_eq!( schema, @@ -79,10 +83,10 @@ assert_eq!( And the same example using a closure wrapped in a `RecursiveTransform`: ``` -# use schemars::{Schema, json_schema}; +# use schemars::{Schema, json_schema, SchemaGenerator}; use schemars::transform::{Transform, RecursiveTransform}; -let mut transform = RecursiveTransform(|schema: &mut Schema| { +let mut transform = RecursiveTransform(|schema: &mut Schema, _: &mut SchemaGenerator| { schema.insert("my_property".to_string(), "hello world".into()); }); @@ -91,7 +95,9 @@ let mut schema = json_schema!({ "items": {} }); -transform.transform(&mut schema); +let mut generator = SchemaGenerator::default(); + +transform.transform(&mut schema, &mut generator); assert_eq!( schema, @@ -106,8 +112,8 @@ assert_eq!( ``` */ -use crate::Schema; use crate::_alloc_prelude::*; +use crate::{Schema, SchemaGenerator}; use alloc::collections::BTreeSet; use serde_json::{json, Map, Value}; @@ -119,7 +125,7 @@ pub trait Transform { /// /// When overriding this method, you may want to call the [`transform_subschemas`] function to /// also transform any subschemas. - fn transform(&mut self, schema: &mut Schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator); // Not public API // Hack to enable implementing Debug on Box even though closures don't @@ -132,15 +138,19 @@ pub trait Transform { impl Transform for F where - F: FnMut(&mut Schema), + F: FnMut(&mut Schema, &mut SchemaGenerator), { - fn transform(&mut self, schema: &mut Schema) { - self(schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + self(schema, generator); } } /// Applies the given [`Transform`] to all direct subschemas of the [`Schema`]. -pub fn transform_subschemas(t: &mut T, schema: &mut Schema) { +pub fn transform_subschemas( + t: &mut T, + schema: &mut Schema, + generator: &mut SchemaGenerator, +) { for (key, value) in schema.as_object_mut().into_iter().flatten() { // This is intentionally written to work with multiple JSON Schema versions, so that // users can add their own transforms on the end of e.g. `SchemaSettings::draft07()` and @@ -157,14 +167,14 @@ pub fn transform_subschemas(t: &mut T, schema: &mut Schem | "propertyNames" | "additionalItems" => { if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } "allOf" | "anyOf" | "oneOf" | "prefixItems" => { if let Some(array) = value.as_array_mut() { for value in array { if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } } @@ -175,18 +185,18 @@ pub fn transform_subschemas(t: &mut T, schema: &mut Schem if let Some(array) = value.as_array_mut() { for value in array { if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } } else if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } "properties" | "patternProperties" | "$defs" | "definitions" => { if let Some(obj) = value.as_object_mut() { for value in obj.values_mut() { if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } } @@ -201,19 +211,20 @@ pub fn transform_subschemas(t: &mut T, schema: &mut Schem pub(crate) fn transform_immediate_subschemas( t: &mut T, schema: &mut Schema, + generator: &mut SchemaGenerator, ) { for (key, value) in schema.as_object_mut().into_iter().flatten() { match key.as_str() { "if" | "then" | "else" => { if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } "allOf" | "anyOf" | "oneOf" => { if let Some(array) = value.as_array_mut() { for value in array { if let Ok(subschema) = value.try_into() { - t.transform(subschema); + t.transform(subschema, generator); } } } @@ -231,19 +242,21 @@ pub(crate) fn transform_immediate_subschemas( /// /// # Example /// ``` -/// # use schemars::{Schema, json_schema}; +/// # use schemars::{Schema, json_schema, SchemaGenerator}; /// use schemars::transform::{Transform, RecursiveTransform}; /// -/// let mut transform = RecursiveTransform(|schema: &mut Schema| { +/// let mut transform = RecursiveTransform(|schema: &mut Schema, _: &mut SchemaGenerator| { /// schema.insert("my_property".to_string(), "hello world".into()); /// }); /// +/// let mut generator = SchemaGenerator::default(); +/// /// let mut schema = json_schema!({ /// "type": "array", /// "items": {} /// }); /// -/// transform.transform(&mut schema); +/// transform.transform(&mut schema, &mut generator); /// /// assert_eq!( /// schema, @@ -263,9 +276,9 @@ impl Transform for RecursiveTransform where T: Transform, { - fn transform(&mut self, schema: &mut Schema) { - self.0.transform(schema); - transform_subschemas(self, schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + self.0.transform(schema, generator); + transform_subschemas(self, schema, generator); } } @@ -282,11 +295,11 @@ pub struct ReplaceBoolSchemas { } impl Transform for ReplaceBoolSchemas { - fn transform(&mut self, schema: &mut Schema) { + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { if let Some(obj) = schema.as_object_mut() { if self.skip_additional_properties { if let Some((ap_key, ap_value)) = obj.remove_entry("additionalProperties") { - transform_subschemas(self, schema); + transform_subschemas(self, schema, generator); schema.insert(ap_key, ap_value); @@ -294,7 +307,7 @@ impl Transform for ReplaceBoolSchemas { } } - transform_subschemas(self, schema); + transform_subschemas(self, schema, generator); } else { schema.ensure_object(); } @@ -310,8 +323,8 @@ impl Transform for ReplaceBoolSchemas { pub struct RemoveRefSiblings; impl Transform for RemoveRefSiblings { - fn transform(&mut self, schema: &mut Schema) { - transform_subschemas(self, schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + transform_subschemas(self, schema, generator); if let Some(obj) = schema.as_object_mut().filter(|o| o.len() > 1) { if let Some(ref_value) = obj.remove("$ref") { @@ -335,8 +348,8 @@ impl Transform for RemoveRefSiblings { pub struct SetSingleExample; impl Transform for SetSingleExample { - fn transform(&mut self, schema: &mut Schema) { - transform_subschemas(self, schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + transform_subschemas(self, schema, generator); if let Some(Value::Array(examples)) = schema.remove("examples") { if let Some(first_example) = examples.into_iter().next() { @@ -355,8 +368,8 @@ impl Transform for SetSingleExample { pub struct ReplaceConstValue; impl Transform for ReplaceConstValue { - fn transform(&mut self, schema: &mut Schema) { - transform_subschemas(self, schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + transform_subschemas(self, schema, generator); if let Some(value) = schema.remove("const") { schema.insert("enum".into(), Value::Array(vec![value])); @@ -376,8 +389,8 @@ impl Transform for ReplaceConstValue { pub struct ReplacePrefixItems; impl Transform for ReplacePrefixItems { - fn transform(&mut self, schema: &mut Schema) { - transform_subschemas(self, schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + transform_subschemas(self, schema, generator); if let Some(prefix_items) = schema.remove("prefixItems") { let previous_items = schema.insert("items".to_owned(), prefix_items); @@ -399,8 +412,8 @@ impl Transform for ReplacePrefixItems { pub struct ReplaceUnevaluatedProperties; impl Transform for ReplaceUnevaluatedProperties { - fn transform(&mut self, schema: &mut Schema) { - transform_subschemas(self, schema); + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { + transform_subschemas(self, schema, generator); let Some(up) = schema.remove("unevaluatedProperties") else { return; @@ -409,7 +422,7 @@ impl Transform for ReplaceUnevaluatedProperties { schema.insert("additionalProperties".to_owned(), up); let mut gather_property_names = GatherPropertyNames::default(); - gather_property_names.transform(schema); + gather_property_names.transform(schema, generator); let property_names = gather_property_names.0; if property_names.is_empty() { @@ -434,7 +447,7 @@ impl Transform for ReplaceUnevaluatedProperties { struct GatherPropertyNames(BTreeSet); impl Transform for GatherPropertyNames { - fn transform(&mut self, schema: &mut Schema) { + fn transform(&mut self, schema: &mut Schema, generator: &mut SchemaGenerator) { self.0.extend( schema .as_object() @@ -445,6 +458,6 @@ impl Transform for GatherPropertyNames { .cloned(), ); - transform_immediate_subschemas(self, schema); + transform_immediate_subschemas(self, schema, generator); } } diff --git a/schemars/tests/integration/deprecated.rs b/schemars/tests/integration/deprecated.rs index 9bdfbef8..0a38a4b5 100644 --- a/schemars/tests/integration/deprecated.rs +++ b/schemars/tests/integration/deprecated.rs @@ -16,7 +16,7 @@ fn deprecated_struct() { test!(DeprecatedStruct) .assert_snapshot() .assert_allows_ser_roundtrip_default() - .custom(|schema, _| { + .custom(|schema, _, _| { assert_eq!( schema.as_value().pointer("/deprecated"), Some(&Value::Bool(true)), @@ -48,7 +48,7 @@ fn deprecated_enum() { test!(DeprecatedEnum) .assert_snapshot() .assert_allows_ser_roundtrip_default() - .custom(|schema, _| { + .custom(|schema, _, _| { assert_eq!( schema.as_value().pointer("/deprecated"), Some(&Value::Bool(true)), diff --git a/schemars/tests/integration/enums.rs b/schemars/tests/integration/enums.rs index f6cd6bcf..3d8a81cc 100644 --- a/schemars/tests/integration/enums.rs +++ b/schemars/tests/integration/enums.rs @@ -339,7 +339,7 @@ fn unit_variants_with_doc_comments() { .assert_snapshot() .assert_allows_ser_roundtrip([SoundOfMusic::Do, SoundOfMusic::Re, SoundOfMusic::Mi]) .assert_rejects_de(arbitrary_values()) - .custom(|schema, _| { + .custom(|schema, _, _| { assert_eq!( schema.as_value().pointer("/oneOf/0/title"), Some(&("A deer".into())), diff --git a/schemars/tests/integration/extend.rs b/schemars/tests/integration/extend.rs index e6f95068..97175dd4 100644 --- a/schemars/tests/integration/extend.rs +++ b/schemars/tests/integration/extend.rs @@ -17,7 +17,7 @@ struct Struct { #[test] fn extend_struct() { - test!(Struct).assert_snapshot().custom(|schema, _| { + test!(Struct).assert_snapshot().custom(|schema, _, _| { assert_eq!(schema.get("obj"), Some(&json!({ "array": [null, null] }))); assert_eq!(schema.get("3"), Some(&json!(3.0))); assert_eq!(schema.get("pi"), Some(&json!(3.14))); @@ -43,7 +43,7 @@ struct TupleStruct( #[test] fn extend_tuple_struct() { - test!(TupleStruct).assert_snapshot().custom(|schema, _| { + test!(TupleStruct).assert_snapshot().custom(|schema, _, _| { assert_eq!(schema.get("obj"), Some(&json!({ "array": [null, null] }))); assert_eq!(schema.get("3"), Some(&json!(3.0))); assert_eq!(schema.get("pi"), Some(&json!(3.14))); @@ -74,16 +74,18 @@ enum ExternalEnum { #[test] fn extend_externally_tagged_enum() { - test!(ExternalEnum).assert_snapshot().custom(|schema, _| { - assert_eq!(schema.get("foo"), Some(&json!("bar"))); - - for i in 0..4 { - assert_eq!( - schema.as_value().pointer(&format!("/oneOf/{i}/foo")), - Some(&json!("bar")) - ); - } - }); + test!(ExternalEnum) + .assert_snapshot() + .custom(|schema, _, _| { + assert_eq!(schema.get("foo"), Some(&json!("bar"))); + + for i in 0..4 { + assert_eq!( + schema.as_value().pointer(&format!("/oneOf/{i}/foo")), + Some(&json!("bar")) + ); + } + }); } #[allow(dead_code)] @@ -100,16 +102,18 @@ enum InternalEnum { #[test] fn extend_internally_tagged_enum() { - test!(InternalEnum).assert_snapshot().custom(|schema, _| { - assert_eq!(schema.get("foo"), Some(&json!("bar"))); - - for i in 0..3 { - assert_eq!( - schema.as_value().pointer(&format!("/oneOf/{i}/foo")), - Some(&json!("bar")) - ); - } - }); + test!(InternalEnum) + .assert_snapshot() + .custom(|schema, _, _| { + assert_eq!(schema.get("foo"), Some(&json!("bar"))); + + for i in 0..3 { + assert_eq!( + schema.as_value().pointer(&format!("/oneOf/{i}/foo")), + Some(&json!("bar")) + ); + } + }); } #[allow(dead_code)] @@ -128,16 +132,18 @@ enum AdjacentEnum { #[test] fn extend_adjacently_tagged_enum() { - test!(AdjacentEnum).assert_snapshot().custom(|schema, _| { - assert_eq!(schema.get("foo"), Some(&json!("bar"))); - - for i in 0..4 { - assert_eq!( - schema.as_value().pointer(&format!("/oneOf/{i}/foo")), - Some(&json!("bar")) - ); - } - }); + test!(AdjacentEnum) + .assert_snapshot() + .custom(|schema, _, _| { + assert_eq!(schema.get("foo"), Some(&json!("bar"))); + + for i in 0..4 { + assert_eq!( + schema.as_value().pointer(&format!("/oneOf/{i}/foo")), + Some(&json!("bar")) + ); + } + }); } #[allow(dead_code)] @@ -156,14 +162,16 @@ enum UntaggedEnum { #[test] fn extend_untagged_enum() { - test!(UntaggedEnum).assert_snapshot().custom(|schema, _| { - assert_eq!(schema.get("foo"), Some(&json!("bar"))); - - for i in 0..4 { - assert_eq!( - schema.as_value().pointer(&format!("/anyOf/{i}/foo")), - Some(&json!("bar")) - ); - } - }); + test!(UntaggedEnum) + .assert_snapshot() + .custom(|schema, _, _| { + assert_eq!(schema.get("foo"), Some(&json!("bar"))); + + for i in 0..4 { + assert_eq!( + schema.as_value().pointer(&format!("/anyOf/{i}/foo")), + Some(&json!("bar")) + ); + } + }); } diff --git a/schemars/tests/integration/schema_name.rs b/schemars/tests/integration/schema_name.rs index e04a7477..633027a3 100644 --- a/schemars/tests/integration/schema_name.rs +++ b/schemars/tests/integration/schema_name.rs @@ -14,10 +14,10 @@ struct RenamedSimpleStruct { #[test] fn simple() { test!(SimpleStruct) - .custom(|schema, _| assert_eq!(schema.get("title"), Some(&"SimpleStruct".into()))); + .custom(|schema, _, _| assert_eq!(schema.get("title"), Some(&"SimpleStruct".into()))); test!(RenamedSimpleStruct) - .custom(|schema, _| assert_eq!(schema.get("title"), Some(&"new-name".into()))); + .custom(|schema, _, _| assert_eq!(schema.get("title"), Some(&"new-name".into()))); } #[derive(JsonSchema, Deserialize, Serialize, Default)] @@ -39,14 +39,14 @@ struct RenamedTypeParams { #[test] fn type_params() { - test!(TypeParams).custom(|schema, _| { + test!(TypeParams).custom(|schema, _, _| { assert_eq!( schema.get("title"), Some(&"TypeParams_for_uint8_and_string_and_boolean_and_null".into()) ) }); - test!(RenamedTypeParams).custom(|schema, _| { + test!(RenamedTypeParams).custom(|schema, _, _| { assert_eq!( schema.get("title"), Some(&"new-name-null-uint8-uint8".into()) @@ -69,7 +69,7 @@ struct RenamedConstGeneric { #[test] fn const_generics() { - test!(ConstGeneric<123, 'X'>).custom(|schema, _| { + test!(ConstGeneric<123, 'X'>).custom(|schema, _, _| { assert_eq!( schema.get("title"), Some(&"ConstGeneric_for_123_and_X".into()) @@ -77,5 +77,5 @@ fn const_generics() { }); test!(RenamedConstGeneric<123, 'X'>) - .custom(|schema, _| assert_eq!(schema.get("title"), Some(&"new-name-123".into()))); + .custom(|schema, _, _| assert_eq!(schema.get("title"), Some(&"new-name-123".into()))); } diff --git a/schemars/tests/integration/settings.rs b/schemars/tests/integration/settings.rs index f6debe6f..033d6a1e 100644 --- a/schemars/tests/integration/settings.rs +++ b/schemars/tests/integration/settings.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use schemars::{generate::SchemaSettings, Schema}; +use schemars::{generate::SchemaSettings, Schema, SchemaGenerator}; #[derive(JsonSchema, Deserialize, Serialize, Default)] pub struct OuterStruct { @@ -53,16 +53,18 @@ fn openapi3() { // First, move them to $defs, then run the transforms, then move them back again. settings.transforms.insert( 0, - Box::new(|s: &mut Schema| { + Box::new(|s: &mut Schema, _: &mut SchemaGenerator| { let obj = s.ensure_object(); let defs = obj["components"]["schemas"].take(); obj.insert("$defs".to_owned(), defs); }), ); - settings.transforms.push(Box::new(|s: &mut Schema| { - let obj = s.ensure_object(); - obj["components"]["schemas"] = obj.remove("$defs").unwrap(); - })); + settings + .transforms + .push(Box::new(|s: &mut Schema, _: &mut SchemaGenerator| { + let obj = s.ensure_object(); + obj["components"]["schemas"] = obj.remove("$defs").unwrap(); + })); test!(OuterStruct, settings).assert_snapshot(); } diff --git a/schemars/tests/integration/test_helper.rs b/schemars/tests/integration/test_helper.rs index 41f937b8..ebcf70d4 100644 --- a/schemars/tests/integration/test_helper.rs +++ b/schemars/tests/integration/test_helper.rs @@ -1,7 +1,7 @@ use jsonschema::Validator; use schemars::{ generate::{Contract, SchemaSettings}, - JsonSchema, Schema, + JsonSchema, Schema, SchemaGenerator, }; use serde::{de::DeserializeOwned, Serialize}; use serde_json::{json, Value}; @@ -131,9 +131,10 @@ impl TestHelper { self } - pub fn custom(&self, assertion: impl Fn(&Schema, Contract)) { - assertion(&self.de_schema, Contract::Deserialize); - assertion(&self.ser_schema, Contract::Serialize); + pub fn custom(&self, assertion: impl Fn(&Schema, &SchemaGenerator, Contract)) { + let generator = SchemaGenerator::default(); + assertion(&self.de_schema, &generator, Contract::Deserialize); + assertion(&self.ser_schema, &generator, Contract::Serialize); } fn de_schema_validate(&self, instance: &Value) -> bool { diff --git a/schemars/tests/integration/transform.rs b/schemars/tests/integration/transform.rs index 94e728a8..90f56793 100644 --- a/schemars/tests/integration/transform.rs +++ b/schemars/tests/integration/transform.rs @@ -1,17 +1,17 @@ use crate::prelude::*; use schemars::{ transform::{RecursiveTransform, Transform}, - Schema, + Schema, SchemaGenerator, }; use serde_json::Map; -fn insert_upper_type(schema: &mut Schema) { +fn insert_upper_type(schema: &mut Schema, _generator: &mut SchemaGenerator) { if let Some(Value::String(ty)) = schema.get("type") { schema.insert("x-upperType".to_owned(), ty.to_uppercase().into()); } } -fn insert_property_count(schema: &mut Schema) { +fn insert_property_count(schema: &mut Schema, _: &mut SchemaGenerator) { let count = schema .get("properties") .and_then(Value::as_object) @@ -53,16 +53,21 @@ fn transform_enum() { .custom(assert_upper_type_valid); } -fn assert_upper_type_valid(schema: &Schema, _: schemars::generate::Contract) { +fn assert_upper_type_valid( + schema: &Schema, + generator: &SchemaGenerator, + _: schemars::generate::Contract, +) { let mut schema = schema.clone(); + let mut generator = generator.clone(); - RecursiveTransform(|s: &mut Schema| { + RecursiveTransform(|s: &mut Schema, _: &mut SchemaGenerator| { assert_eq!( s.remove("x-upperType").map(|v| v.to_string()), s.get("type").map(|v| v.to_string().to_uppercase()), ); }) - .transform(&mut schema); + .transform(&mut schema, &mut generator); assert!(!schema.to_value().to_string().contains("x-upperType")); } diff --git a/schemars/tests/ui/transform_str.stderr b/schemars/tests/ui/transform_str.stderr index 50cf7b94..d1f037a8 100644 --- a/schemars/tests/ui/transform_str.stderr +++ b/schemars/tests/ui/transform_str.stderr @@ -1,4 +1,4 @@ -error: Expected a `fn(&mut Schema)` or other value implementing `schemars::transform::Transform`, found `&str`. +error: Expected a `fn(&mut Schema, &mut SchemaGenerator)` or other value implementing `schemars::transform::Transform`, found `&str`. Did you mean `#[schemars(transform = x)]`? --> tests/ui/transform_str.rs:4:24 | diff --git a/schemars_derive/src/attr/mod.rs b/schemars_derive/src/attr/mod.rs index 37350d33..b03d4188 100644 --- a/schemars_derive/src/attr/mod.rs +++ b/schemars_derive/src/attr/mod.rs @@ -11,7 +11,7 @@ use syn::Ident; use syn::{punctuated::Punctuated, Attribute, Expr, ExprLit, Lit, Meta, Path, Type}; use validation::ValidationAttrs; -use crate::idents::SCHEMA; +use crate::idents::{GENERATOR, SCHEMA}; pub use schemars_to_serde::process_serde_attrs; @@ -131,7 +131,7 @@ impl CommonAttrs { cx.error_spanned_by( &expr, format_args!( - "Expected a `fn(&mut Schema)` or other value implementing `schemars::transform::Transform`, found `&str`.\nDid you mean `#[schemars(transform = {})]`?", + "Expected a `fn(&mut Schema, &mut SchemaGenerator)` or other value implementing `schemars::transform::Transform`, found `&str`.\nDid you mean `#[schemars(transform = {})]`?", lit_str.value() ), ) @@ -211,7 +211,7 @@ impl CommonAttrs { for transform in &self.transforms { mutators.push(quote! { - schemars::transform::Transform::transform(&mut #transform, &mut #SCHEMA); + schemars::transform::Transform::transform(&mut #transform, &mut #SCHEMA, #GENERATOR); }); } }