Skip to content

Commit 93ce470

Browse files
committed
feat: evaluate() top-level function for convenient access to structured validation output
Signed-off-by: Dmitry Dygalo <[email protected]>
1 parent 8344bc0 commit 93ce470

File tree

3 files changed

+62
-6
lines changed

3 files changed

+62
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## [Unreleased]
44

5+
### Added
6+
7+
- `evaluate()` top-level function for convenient access to structured validation output.
8+
59
### Changed
610

711
- **BREAKING**: `ValidationError` fields are private; use `instance()`, `kind()`, `instance_path()`, and `schema_path()` instead of accessing struct fields directly.

crates/jsonschema/benches/jsonschema.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ mod bench {
1818
BenchmarkId::new("is_valid", name),
1919
instance,
2020
|b, instance| {
21-
b.iter(|| {
22-
let _ = validator.is_valid(instance);
23-
});
21+
b.iter(|| black_box(validator.is_valid(instance)));
2422
},
2523
);
2624
}
@@ -31,9 +29,7 @@ mod bench {
3129
BenchmarkId::new("validate", name),
3230
instance,
3331
|b, instance| {
34-
b.iter(|| {
35-
let _ = validator.validate(instance);
36-
});
32+
b.iter(|| black_box(validator.validate(instance)));
3733
},
3834
);
3935
}

crates/jsonschema/src/lib.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,33 @@ pub fn validate<'i>(schema: &Value, instance: &'i Value) -> Result<(), Validatio
976976
.validate(instance)
977977
}
978978

979+
/// Evaluate `instance` against `schema` and return structured validation output. Draft is detected automatically.
980+
///
981+
/// Returns an [`Evaluation`] containing detailed validation results in JSON Schema Output v1 format,
982+
/// including annotations and errors across the entire validation tree.
983+
///
984+
/// # Examples
985+
///
986+
/// ```rust
987+
/// use serde_json::json;
988+
///
989+
/// let schema = json!({"type": "string", "minLength": 3});
990+
/// let instance = json!("foo");
991+
/// let evaluation = jsonschema::evaluate(&schema, &instance);
992+
/// assert!(evaluation.flag().valid);
993+
/// ```
994+
///
995+
/// # Panics
996+
///
997+
/// This function panics if an invalid schema is passed.
998+
#[must_use]
999+
#[inline]
1000+
pub fn evaluate(schema: &Value, instance: &Value) -> Evaluation {
1001+
validator_for(schema)
1002+
.expect("Invalid schema")
1003+
.evaluate(instance)
1004+
}
1005+
9791006
/// Create a validator for the input schema with automatic draft detection and default options.
9801007
///
9811008
/// # Examples
@@ -2724,6 +2751,35 @@ mod tests {
27242751
assert!(validate_fn(&schema, &invalid_instance).is_err());
27252752
}
27262753

2754+
#[test]
2755+
fn test_evaluate() {
2756+
let schema = json!({
2757+
"type": "object",
2758+
"properties": {
2759+
"name": {"type": "string"},
2760+
"age": {"type": "integer", "minimum": 0}
2761+
},
2762+
"required": ["name"]
2763+
});
2764+
2765+
let valid_instance = json!({
2766+
"name": "John Doe",
2767+
"age": 30
2768+
});
2769+
2770+
let invalid_instance = json!({
2771+
"age": -5
2772+
});
2773+
2774+
let valid_eval = crate::evaluate(&schema, &valid_instance);
2775+
assert!(valid_eval.flag().valid);
2776+
2777+
let invalid_eval = crate::evaluate(&schema, &invalid_instance);
2778+
assert!(!invalid_eval.flag().valid);
2779+
let errors: Vec<_> = invalid_eval.iter_errors().collect();
2780+
assert!(!errors.is_empty());
2781+
}
2782+
27272783
#[test_case(crate::meta::validate, crate::meta::is_valid ; "autodetect")]
27282784
#[test_case(crate::draft4::meta::validate, crate::draft4::meta::is_valid ; "draft4")]
27292785
#[test_case(crate::draft6::meta::validate, crate::draft6::meta::is_valid ; "draft6")]

0 commit comments

Comments
 (0)