From 71a511d6349b2cae955264cd26bc489f08e8dc99 Mon Sep 17 00:00:00 2001 From: Pawel Iwan Date: Thu, 23 Jun 2022 08:59:25 +0200 Subject: [PATCH] feat: optional unknown formats as compilation error --- jsonschema/src/compilation/options.rs | 16 +++++++++++++++ jsonschema/src/keywords/format.rs | 29 +++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/jsonschema/src/compilation/options.rs b/jsonschema/src/compilation/options.rs index 1722662..6690f9d 100644 --- a/jsonschema/src/compilation/options.rs +++ b/jsonschema/src/compilation/options.rs @@ -221,6 +221,7 @@ pub struct CompilationOptions { formats: AHashMap<&'static str, fn(&str) -> bool>, validate_formats: Option, validate_schema: bool, + ignore_unknown_formats: bool, } impl Default for CompilationOptions { @@ -234,6 +235,7 @@ impl Default for CompilationOptions { store: AHashMap::default(), formats: AHashMap::default(), validate_formats: None, + ignore_unknown_formats: true, } } } @@ -568,6 +570,20 @@ impl CompilationOptions { self.validate_formats .unwrap_or_else(|| self.draft().validate_formats_by_default()) } + + /// Set the `false` if unrecognized formats should be reported as a validation error. + /// By default unknown formats are silently ignored. + pub fn should_ignore_unknown_formats( + &mut self, + should_ignore_unknown_formats: bool, + ) -> &mut Self { + self.ignore_unknown_formats = should_ignore_unknown_formats; + self + } + + pub(crate) const fn are_unknown_formats_ignored(&self) -> bool { + self.ignore_unknown_formats + } } // format name & a pointer to a check function type FormatKV<'a> = Option<(&'a &'static str, &'a fn(&str) -> bool)>; diff --git a/jsonschema/src/keywords/format.rs b/jsonschema/src/keywords/format.rs index 082052c..9435278 100644 --- a/jsonschema/src/keywords/format.rs +++ b/jsonschema/src/keywords/format.rs @@ -493,7 +493,18 @@ pub(crate) fn compile<'a>( "duration" if draft_version == Draft::Draft201909 => { Some(DurationValidator::compile(context)) } - _ => None, + _ => { + if context.config.are_unknown_formats_ignored() { + None + } else { + return Some(Err(ValidationError::format( + JSONPointer::default(), + context.clone().schema_path.into(), + schema, + "unknown format", + ))); + } + } } } else { Some(Err(ValidationError::single_type_error( @@ -511,7 +522,7 @@ mod tests { #[cfg(feature = "draft201909")] use crate::schemas::Draft::Draft201909; - use crate::{compilation::JSONSchema, tests_util}; + use crate::{compilation::JSONSchema, error::ValidationErrorKind, tests_util}; #[test] fn ignored_format() { @@ -606,4 +617,18 @@ mod tests { assert!(!compiled.is_valid(&failing_instance)); } } + + #[test] + fn unknown_formats_should_not_be_ignored() { + let schema = json!({ "format": "custom", "type": "string"}); + let validation_error = JSONSchema::options() + .should_ignore_unknown_formats(false) + .compile(&schema) + .expect_err("the validation error should be returned"); + + assert!( + matches!(validation_error.kind, ValidationErrorKind::Format { format } if format == "unknown format") + ); + assert_eq!("\"custom\"", validation_error.instance.to_string()) + } }