WIP
diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_validators.py
index 141f15a..5cb6148 100644
--- a/jsonschema/_legacy_validators.py
+++ b/jsonschema/_legacy_validators.py
@@ -1,7 +1,7 @@
from referencing.jsonschema import lookup_recursive_ref
from jsonschema import _utils
-from jsonschema.exceptions import ValidationError
+from jsonschema.exceptions import ValidationError, keywords
def ignore_ref_siblings(schema):
@@ -160,7 +160,7 @@
schema_path=property,
)
elif subschema.get("required", False):
- error = ValidationError(f"{property!r} is a required property")
+ error = keywords.Required(property_name=property)
error._set(
validator="required",
validator_value=subschema["required"],
diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py
index 45b53c9..820a79c 100644
--- a/jsonschema/_validators.py
+++ b/jsonschema/_validators.py
@@ -1,6 +1,7 @@
from fractions import Fraction
import re
+from jsonschema import exceptions
from jsonschema._utils import (
ensure_list,
equal,
@@ -12,6 +13,7 @@
uniq,
)
from jsonschema.exceptions import FormatError, ValidationError
+import jsonschema.exceptions.keywords # noqa: F401
def patternProperties(validator, patternProperties, instance, schema):
@@ -315,7 +317,7 @@
return
for property in required:
if property not in instance:
- yield ValidationError(f"{property!r} is a required property")
+ yield exceptions.keywords.Required(property_name=property)
def minProperties(validator, mP, instance, schema):
diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions/__init__.py
similarity index 100%
rename from jsonschema/exceptions.py
rename to jsonschema/exceptions/__init__.py
diff --git a/jsonschema/exceptions/keywords.py b/jsonschema/exceptions/keywords.py
new file mode 100644
index 0000000..9cb37f6
--- /dev/null
+++ b/jsonschema/exceptions/keywords.py
@@ -0,0 +1,11 @@
+from jsonschema.exceptions import ValidationError
+
+
+class Required(ValidationError):
+ def __init__(self, property_name):
+ ValidationError.__init__(
+ self,
+ message=f"{property_name!r} is a required property",
+ )
+
+ self.property_name = property_name
diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py
index 940a86d..f638b95 100644
--- a/jsonschema/tests/test_validators.py
+++ b/jsonschema/tests/test_validators.py
@@ -24,6 +24,7 @@
protocols,
validators,
)
+import jsonschema.exceptions.keywords
def fail(validator, errors, instance, schema):
@@ -1760,6 +1761,18 @@
with self.assertRaises(exceptions.ValidationError):
validator.validate(instance)
+ def test_required_missing(self):
+ if self.Validator is not validators.Draft3Validator:
+ schema = {"required": ["a", "b"]}
+ else:
+ required = dict(required=True)
+ schema = {"properties": dict(a=required, b=required)}
+ validator = self.Validator(schema)
+
+ with self.assertRaises(exceptions.keywords.Required) as e:
+ validator.validate({"a": 37})
+ self.assertEqual(e.exception.property_name, "b")
+
def test_it_creates_a_ref_resolver_if_not_provided(self):
with self.assertWarns(DeprecationWarning):
resolver = self.Validator({}).resolver