From 0091e5c2267514475f394b1092ecd9d7e8a3e80a Mon Sep 17 00:00:00 2001 From: Satya Date: Tue, 26 May 2026 16:47:04 -0400 Subject: [PATCH] feat: support inline json schema validation dynamically --- src/validator/mod.rs | 115 +++++++++++++++++++++++++------------------ 1 file changed, 68 insertions(+), 47 deletions(-) diff --git a/src/validator/mod.rs b/src/validator/mod.rs index 87b2efd..e134b4c 100644 --- a/src/validator/mod.rs +++ b/src/validator/mod.rs @@ -42,62 +42,83 @@ impl Validator { } pub fn validate(&self, schema_id: &str, instance: &Value) -> crate::drop::Drop { - let schema_opt = self.db.schemas.get(schema_id); - - if let Some(schema) = schema_opt { - let ctx = ValidationContext::new( - &self.db, - &schema, - &schema, - instance, - HashSet::new(), - false, - false, - ); - match ctx.validate_scoped() { - Ok(result) => { - if result.is_valid() { - crate::drop::Drop::success() - } else { - let errors: Vec = result - .errors - .into_iter() - .map(|e| crate::drop::Error { - code: e.code, - message: e.message, - details: crate::drop::ErrorDetails { - path: Some(e.path), - cause: None, - context: None, - schema: None, - }, - }) - .collect(); - crate::drop::Drop::with_errors(errors) + let schema_arc = if schema_id.trim().starts_with('{') { + match serde_json::from_str::(schema_id) { + Ok(schema) => { + let mut errors = Vec::new(); + schema.compile(&self.db, "inline", "inline".to_string(), &mut errors); + if !errors.is_empty() { + return crate::drop::Drop::with_errors(errors); } + Arc::new(schema) + } + Err(e) => { + return crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: "SCHEMA_PARSE_FAILED".to_string(), + message: format!("Failed to parse inline schema: {}", e), + details: crate::drop::ErrorDetails::default(), + }]); } - Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { - code: e.code, - message: e.message, - details: crate::drop::ErrorDetails { - path: Some(e.path), - cause: None, - context: None, - schema: None, - }, - }]), } } else { - crate::drop::Drop::with_errors(vec![crate::drop::Error { - code: "SCHEMA_NOT_FOUND".to_string(), - message: format!("Schema {} not found", schema_id), + match self.db.schemas.get(schema_id) { + Some(schema) => Arc::clone(schema), + None => { + return crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: "SCHEMA_NOT_FOUND".to_string(), + message: format!("Schema {} not found", schema_id), + details: crate::drop::ErrorDetails { + path: Some("/".to_string()), + cause: None, + context: None, + schema: None, + }, + }]); + } + } + }; + + let ctx = ValidationContext::new( + &self.db, + &schema_arc, + &schema_arc, + instance, + HashSet::new(), + false, + false, + ); + match ctx.validate_scoped() { + Ok(result) => { + if result.is_valid() { + crate::drop::Drop::success() + } else { + let errors: Vec = result + .errors + .into_iter() + .map(|e| crate::drop::Error { + code: e.code, + message: e.message, + details: crate::drop::ErrorDetails { + path: Some(e.path), + cause: None, + context: None, + schema: None, + }, + }) + .collect(); + crate::drop::Drop::with_errors(errors) + } + } + Err(e) => crate::drop::Drop::with_errors(vec![crate::drop::Error { + code: e.code, + message: e.message, details: crate::drop::ErrorDetails { - path: Some("/".to_string()), + path: Some(e.path), cause: None, context: None, schema: None, }, - }]) + }]), } } }