use schemars::{JsonSchema, generate::SchemaSettings};
use serde_json::Value;
use crate::{config::ConfigResult, config_util::ensure_single_trailing_newline};
pub fn root_config_schema<S>() -> ConfigResult<Value>
where
S: JsonSchema,
{
let generator = SchemaSettings::draft07().into_generator();
let schema = generator.into_root_schema_for::<S>();
let mut schema = serde_json::to_value(schema)?;
remove_required_recursively(&mut schema);
Ok(schema)
}
pub fn schema_json(schema: &Value) -> ConfigResult<String> {
let mut json = serde_json::to_string_pretty(schema)?;
ensure_single_trailing_newline(&mut json);
Ok(json)
}
fn remove_required_recursively(value: &mut Value) {
match value {
Value::Object(object) => {
object.remove("required");
for (key, child) in object.iter_mut() {
if is_schema_map_key(key) {
remove_required_from_schema_map(child);
} else {
remove_required_recursively(child);
}
}
}
Value::Array(items) => {
for item in items {
remove_required_recursively(item);
}
}
Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => {}
}
}
fn is_schema_map_key(key: &str) -> bool {
matches!(
key,
"$defs" | "definitions" | "properties" | "patternProperties"
)
}
fn remove_required_from_schema_map(value: &mut Value) {
match value {
Value::Object(object) => {
for schema in object.values_mut() {
remove_required_recursively(schema);
}
}
_ => remove_required_recursively(value),
}
}