Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add ValidationOptions::with_registry #685

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [Unreleased]

### Added

- Re-export `referencing::Registry` as `jsonschema::Registry`.
- `ValidationOptions::with_registry` that allows for providing a predefined `referencing::Registry`. [#682](https://github.com/Stranger6667/jsonschema/issues/682)

## [0.28.3] - 2025-01-24

### Fixed
Expand Down
6 changes: 6 additions & 0 deletions crates/jsonschema-referencing/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,12 @@ impl Registry {
_ => unreachable!(),
}
}

pub fn resources(&self) -> impl Iterator<Item = (&Uri<String>, Arc<Resource>)> {
self.resources
.iter()
.map(|(uri, resource)| (uri, Arc::clone(resource)))
}
}

fn process_resources(
Expand Down
2 changes: 1 addition & 1 deletion crates/jsonschema/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ pub use error::{ErrorIterator, MaskedValidationError, ValidationError};
pub use keywords::custom::Keyword;
pub use options::ValidationOptions;
pub use output::BasicOutput;
pub use referencing::{Draft, Error as ReferencingError, Resource, Retrieve, Uri};
pub use referencing::{Draft, Error as ReferencingError, Registry, Resource, Retrieve, Uri};
pub use validator::Validator;

use serde_json::Value;
Expand Down
57 changes: 57 additions & 0 deletions crates/jsonschema/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,42 @@ impl ValidationOptions {
}
self
}

/// Use external schema resources from the registry, making them accessible via references
/// during validation.
///
/// # Example
///
/// ```rust
/// # use serde_json::json;
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use jsonschema::{Registry, Resource};
///
/// let registry = Registry::try_new(
/// "urn:name-schema",
/// Resource::from_contents(json!({"type": "string"}))?
/// )?;
/// let schema = json!({
/// "properties": {
/// "name": { "$ref": "urn:name-schema" }
/// }
/// });
/// let validator = jsonschema::options()
/// .with_registry(registry)
/// .build(&schema)?;
/// assert!(validator.is_valid(&json!({ "name": "Valid String" })));
/// assert!(!validator.is_valid(&json!({ "name": 123 })));
/// # Ok(())
/// # }
/// ```
pub fn with_registry(&mut self, registry: referencing::Registry) -> &mut Self {
// NOTE: This is not particularly efficient, and should be changed in the future
for (uri, resource) in registry.resources() {
self.resources
.insert(uri.as_str().to_string(), (*resource).clone());
}
self
}
/// Register a custom format validator.
///
/// # Example
Expand Down Expand Up @@ -467,6 +503,7 @@ impl fmt::Debug for ValidationOptions {

#[cfg(test)]
mod tests {
use referencing::{Registry, Resource};
use serde_json::json;

fn custom(s: &str) -> bool {
Expand All @@ -484,4 +521,24 @@ mod tests {
assert!(!validator.is_valid(&json!("foo")));
assert!(validator.is_valid(&json!("foo42!")));
}

#[test]
fn with_registry() {
let registry = Registry::try_new(
"urn:name-schema",
Resource::from_contents(json!({"type": "string"})).expect("Invalid resource"),
)
.expect("Invalid URI");
let schema = json!({
"properties": {
"name": { "$ref": "urn:name-schema" }
}
});
let validator = crate::options()
.with_registry(registry)
.build(&schema)
.expect("Invalid schema");
assert!(validator.is_valid(&json!({ "name": "Valid String" })));
assert!(!validator.is_valid(&json!({ "name": 123 })));
}
}
Loading