child_ai_json_engine 0.0.2

Crate provides a JSON engine for collecting, aggregating, and managing models.
Documentation
use crate::config::json::Value as JsonValue;
use std::collections::HashMap;
use std::path::Path;

pub struct SchemaValidator {
    schemas: HashMap<String, JsonValue>,
}

impl SchemaValidator {
    pub fn new(schemas_dir: &Path) -> Result<Self, String> {
        let mut schemas = HashMap::new();

        let schema_types = vec!["engine_execution", "comparison_result", "training_sample"];

        for schema_type in schema_types {
            let schema_path = schemas_dir.join("v1").join(format!("{}.json", schema_type));
            match std::fs::read_to_string(&schema_path) {
                Ok(schema_content) => match schema_content.parse::<JsonValue>() {
                    Ok(schema_value) => {
                        schemas.insert(schema_type.to_string(), schema_value);
                    }
                    Err(e) => {
                        eprintln!("Warning: failed to parse schema {:?}: {}", schema_path, e);
                    }
                },
                Err(e) => {
                    eprintln!("Warning: missing schema {:?}: {}", schema_path, e);
                }
            }
        }

        Ok(Self { schemas })
    }

    pub fn validate(&self, data: &JsonValue, schema_type: &str) -> Result<(), String> {
        let schema_value = match self.schemas.get(schema_type) {
            Some(s) => s,
            None => {
                eprintln!(
                    "[validator] warning: schema not found for {}, permissive mode",
                    schema_type
                );
                return Ok(());
            }
        };

        if matches!(data, JsonValue::Null) {
            return Err("Payload is null".to_string());
        }

        if let JsonValue::Object(schema_obj) = schema_value {
            if let Some(JsonValue::Array(arr)) = schema_obj.get("required") {
                for item in arr.iter() {
                    if let JsonValue::String(field) = item {
                        if let JsonValue::Object(dobj) = data {
                            if !dobj.contains_key(field) {
                                return Err(format!("Missing required field: {}", field));
                            }
                        } else {
                            return Err("Payload is not an object".to_string());
                        }
                    }
                }
            }
        }

        Ok(())
    }

    pub fn validate_or_error(&self, data: &JsonValue, schema_type: &str) -> Result<(), String> {
        self.validate(data, schema_type)
            .map_err(|e| format!("Validation failed: {}", e))
    }
}