use schemars::schema::RootSchema;
#[must_use]
pub fn schema_for<T: schemars::JsonSchema>() -> RootSchema {
schemars::schema_for!(T)
}
pub const SERIALIZED_EXTENSION: &str = "x-wyrd-serialized";
pub fn skipped_option<T: schemars::JsonSchema>(
generator: &mut schemars::r#gen::SchemaGenerator,
) -> schemars::schema::Schema {
let serialized = serde_json::to_value(generator.subschema_for::<T>())
.expect("a schemars schema always serializes to JSON");
let mut schema = generator.subschema_for::<Option<T>>().into_object();
schema
.extensions
.insert(SERIALIZED_EXTENSION.to_owned(), serialized);
schema.into()
}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
use serde_json::json;
#[derive(Serialize, Deserialize, schemars::JsonSchema)]
struct Skipped {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(schema_with = "super::skipped_option::<String>")]
scalar: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schemars(schema_with = "super::skipped_option::<serde_json::Value>")]
opaque: Option<serde_json::Value>,
}
#[test]
fn skipped_option_keeps_input_schema_and_records_serialized_value() {
let schema = serde_json::to_value(super::schema_for::<Skipped>()).expect("schema JSON");
assert_eq!(schema.get("required"), None);
let scalar = &schema["properties"]["scalar"];
assert_eq!(scalar["type"], json!(["string", "null"]));
assert_eq!(
scalar[super::SERIALIZED_EXTENSION],
json!({"type": "string"})
);
assert_eq!(
schema["properties"]["opaque"][super::SERIALIZED_EXTENSION],
json!(true)
);
}
}