Skip to content

Commit

Permalink
Validate more deeply required attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
horejsek committed Jun 15, 2024
1 parent efc04da commit d2fbc8f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 6 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
=== 2.20.0 (2024-06-15)

* Added validations at compile time:
* `required` must have unique items
* checking if schema is not allowing `required` items (item is required, but is not listed in properties)

=== 2.19.1 (2023-12-28)

* Fixed date format to accept only two digit months and days
Expand Down
12 changes: 12 additions & 0 deletions fastjsonschema/draft04.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,18 @@ def generate_required(self):
with self.l('if {variable}_is_dict:'):
if not isinstance(self._definition['required'], (list, tuple)):
raise JsonSchemaDefinitionException('required must be an array')
if len(self._definition['required']) != len(set(self._definition['required'])):
raise JsonSchemaDefinitionException('required must contain unique elements')
if not self._definition.get('additionalProperties', True):
not_possible = [
prop
for prop in self._definition['required']
if
prop not in self._definition.get('properties', {})
and not any(re.search(regex, prop) for regex in self._definition.get('patternProperties', {}))
]
if not_possible:
raise JsonSchemaDefinitionException('{}: items {} are required but not allowed'.format(self._variable, not_possible))
self.l('{variable}__missing_keys = set({required}) - {variable}.keys()')
with self.l('if {variable}__missing_keys:'):
dynamic = 'str(sorted({variable}__missing_keys)) + " properties"'
Expand Down
2 changes: 1 addition & 1 deletion fastjsonschema/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '2.19.1'
VERSION = '2.20.0'
50 changes: 45 additions & 5 deletions tests/test_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,53 @@ def test_properties(asserter, value, expected):
}, value, expected)


def test_invalid_properties(asserter):
@pytest.mark.parametrize('definition', (
{
'properties': {
'item': ['wrong'],
},
},
{
'properties': {
'x': {
'type': 'number',
},
},
'required': ['x', 'y'],
'additionalProperties': False,
},
{
'properties': {
'x': {
'type': 'number',
},
},
'required': ['x', 'x'],
}
))
def test_invalid_properties(asserter, definition):
with pytest.raises(JsonSchemaDefinitionException):
fastjsonschema.compile({
'properties': {
'item': ['wrong'],
fastjsonschema.compile(definition)


@pytest.mark.parametrize('definition', (
{
'properties': {
'x': {
'type': 'number',
},
},
'patternProperties': {
'^y': {
'type': 'number',
},
})
},
'required': ['x', 'y'],
'additionalProperties': False,
},
))
def test_valid_properties(asserter, definition):
asserter(definition, {'x': 1, 'y': 2}, {'x': 1, 'y': 2})


@pytest.mark.parametrize('value, expected', [
Expand Down

0 comments on commit d2fbc8f

Please sign in to comment.