use crate::prelude::*; use schemars::generate::SchemaSettings; #[derive(JsonSchema, Deserialize, Serialize, Default)] struct Struct { #[serde(with = "int_as_str")] #[schemars(schema_with = "int_as_str::json_schema")] x: i64, #[schemars(schema_with = "from_serialize_default::")] t: T, } mod int_as_str { pub(super) fn serialize(value: &T, ser: S) -> Result where S: serde::Serializer, T: std::fmt::Display, { ser.collect_str(value) } pub(super) fn deserialize<'de, D, T>(deser: D) -> Result where D: serde::Deserializer<'de>, T: std::str::FromStr, { <&str as serde::Deserialize>::deserialize(deser)? .parse() .map_err(serde::de::Error::custom) } pub(super) fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema { schemars::json_schema!({ "type": "string", "pattern": r"^-?\d+$" }) } } fn from_serialize_default( generator: &mut schemars::SchemaGenerator, ) -> schemars::Schema { generator .settings() .clone() .into_generator() .into_root_schema_for_value(&T::default()) .unwrap() } #[test] fn field_schema_with() { test!(Struct) .assert_snapshot() .assert_allows_ser_roundtrip_default() .assert_matches_de_roundtrip(arbitrary_values_except( Value::is_array, "structs with `#derive(Deserialize)` can technically be deserialized from sequences, but that's not intended to be used via JSON, so schemars ignores it", )); } struct NotJsonSchema; #[derive(JsonSchema)] #[schemars(with = "Struct")] struct Struct2 { _x: NotJsonSchema, } #[test] fn container_with() { test!(Struct2).assert_identical::>(); } #[derive(JsonSchema)] #[schemars(with = "Struct", description = "Testing...")] struct Struct3 { _x: NotJsonSchema, } #[test] fn container_with_metadata() { test!(Struct3).assert_snapshot().custom(|schema, _| { assert_eq!(schema.get("description"), Some(&"Testing...".into())); }); assert_ne!(::schema_id(), ::schema_id()); } #[derive(JsonSchema)] #[schemars(schema_with = "int_as_str::json_schema")] struct IntAsString { _x: NotJsonSchema, } #[test] fn container_schema_with() { test!(IntAsString) .assert_snapshot() .custom(|schema, contract| { let mut generator = SchemaSettings::default() .with(|s| s.contract = contract) .into_generator(); let expected = int_as_str::json_schema(&mut generator); // `title` and `$schema` are added for root schemas - ignore for comparison purposes let mut schema = schema.clone(); schema.remove("title"); schema.remove("$schema"); assert_eq!(schema, expected); }); }