dynamic type variables now recursive

This commit is contained in:
2026-06-03 10:50:15 -04:00
parent 843891f67e
commit c71e99527d
4 changed files with 73 additions and 6 deletions

View File

@ -37,6 +37,14 @@
},
"filter": {
"type": "$kind.filter"
},
"conditions": {
"type": "object",
"properties": {
"new": { "type": "$kind.filter" },
"old": { "type": "$kind.filter" },
"complete": { "type": "$kind.filter" }
}
}
}
}
@ -149,7 +157,48 @@
}
]
}
},
{
"description": "Valid nested filter payload",
"data": {
"kind": "person",
"conditions": {
"new": {
"age": 30
}
}
},
"schema_id": "search",
"action": "validate",
"expect": {
"success": true
}
},
{
"description": "Invalid nested filter payload (fails constraint)",
"data": {
"kind": "person",
"conditions": {
"new": {
"age": "thirty"
}
}
},
"schema_id": "search",
"action": "validate",
"expect": {
"success": false,
"errors": [
{
"code": "INVALID_TYPE",
"details": {
"path": "conditions/new/age"
}
}
]
}
}
]
}
]

View File

@ -1277,6 +1277,18 @@ fn test_dynamic_type_0_4() {
crate::tests::runner::run_test_case(&path, 0, 4).unwrap();
}
#[test]
fn test_dynamic_type_0_5() {
let path = format!("{}/fixtures/dynamicType.json", env!("CARGO_MANIFEST_DIR"));
crate::tests::runner::run_test_case(&path, 0, 5).unwrap();
}
#[test]
fn test_dynamic_type_0_6() {
let path = format!("{}/fixtures/dynamicType.json", env!("CARGO_MANIFEST_DIR"));
crate::tests::runner::run_test_case(&path, 0, 6).unwrap();
}
#[test]
fn test_property_names_0_0() {
let path = format!("{}/fixtures/propertyNames.json", env!("CARGO_MANIFEST_DIR"));

View File

@ -15,7 +15,7 @@ pub struct ValidationContext<'a> {
pub extensible: bool,
pub reporter: bool,
pub overrides: HashSet<String>,
pub parent: Option<&'a serde_json::Value>,
pub parents: Vec<&'a serde_json::Value>,
}
impl<'a> ValidationContext<'a> {
@ -39,7 +39,7 @@ impl<'a> ValidationContext<'a> {
extensible: effective_extensible,
reporter,
overrides,
parent: None,
parents: Vec::new(),
}
}
@ -63,6 +63,11 @@ impl<'a> ValidationContext<'a> {
) -> Self {
let effective_extensible = schema.extensible.unwrap_or(extensible);
let mut parents = self.parents.clone();
if let Some(p) = parent_instance {
parents.push(p);
}
Self {
db: self.db,
root: self.root,
@ -73,7 +78,7 @@ impl<'a> ValidationContext<'a> {
extensible: effective_extensible,
reporter,
overrides,
parent: parent_instance,
parents,
}
}
@ -85,7 +90,7 @@ impl<'a> ValidationContext<'a> {
HashSet::new(),
self.extensible,
reporter,
self.parent,
None,
)
}

View File

@ -59,12 +59,13 @@ impl<'a> ValidationContext<'a> {
};
let mut resolved = false;
if let Some(parent) = self.parent {
for parent in self.parents.iter().rev() {
if let Some(obj) = parent.as_object() {
if let Some(val) = obj.get(var_name) {
if let Some(str_val) = val.as_str() {
target_id = format!("{}{}", str_val, suffix);
resolved = true;
break;
}
}
}
@ -97,7 +98,7 @@ impl<'a> ValidationContext<'a> {
new_overrides,
self.extensible,
true, // Reporter mode
self.parent,
None,
);
shadow.root = &global_schema;
result.merge(shadow.validate()?);