diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a1464e7..6d192a87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- only check minProperties or maxProperties on objects ([#802](https://github.com/jsonrainbow/json-schema/pull/802)) ## [6.2.1] - 2025-03-06 ### Fixed diff --git a/src/JsonSchema/Constraints/ObjectConstraint.php b/src/JsonSchema/Constraints/ObjectConstraint.php index 0752ac13..e55d7656 100644 --- a/src/JsonSchema/Constraints/ObjectConstraint.php +++ b/src/JsonSchema/Constraints/ObjectConstraint.php @@ -175,15 +175,19 @@ protected function &getProperty(&$element, $property, $fallback = null) */ protected function validateMinMaxConstraint($element, $objectDefinition, ?JsonPointer $path = null) { + if (!$this->getTypeCheck()::isObject($element)) { + return; + } + // Verify minimum number of properties - if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) { - if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) { + if (isset($objectDefinition->minProperties) && is_int($objectDefinition->minProperties)) { + if ($this->getTypeCheck()->propertyCount($element) < max(0, $objectDefinition->minProperties)) { $this->addError(ConstraintError::PROPERTIES_MIN(), $path, ['minProperties' => $objectDefinition->minProperties]); } } // Verify maximum number of properties - if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) { - if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) { + if (isset($objectDefinition->maxProperties) && is_int($objectDefinition->maxProperties)) { + if ($this->getTypeCheck()->propertyCount($element) > max(0, $objectDefinition->maxProperties)) { $this->addError(ConstraintError::PROPERTIES_MAX(), $path, ['maxProperties' => $objectDefinition->maxProperties]); } } diff --git a/tests/Constraints/MinMaxPropertiesTest.php b/tests/Constraints/MinMaxPropertiesTest.php index bf3a3182..2de94329 100644 --- a/tests/Constraints/MinMaxPropertiesTest.php +++ b/tests/Constraints/MinMaxPropertiesTest.php @@ -9,6 +9,8 @@ namespace JsonSchema\Tests\Constraints; +use JsonSchema\Constraints\Constraint; + class MinMaxPropertiesTest extends BaseTestCase { protected $validateSchema = true; @@ -19,50 +21,71 @@ class MinMaxPropertiesTest extends BaseTestCase public function getValidTests(): array { return [ - [ - '{ + 'Empty object with minProperties: 0' => [ + 'input' => '{ "value": {} }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "minProperties": 0} } }' ], - [ - '{ + 'Empty object with maxProperties: 1' => [ + 'input' => '{ "value": {} }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "maxProperties": 1} } }' ], - [ - '{ + 'Empty object with minProperties: 0 and maxProperties: 1' => [ + 'input' => '{ "value": {} }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "minProperties": 0,"maxProperties": 1} } }' ], - [ - '{ + 'Object with two properties with minProperties: 1 and maxProperties: 2' => [ + 'input' => '{ "value": {"foo": 1, "bar": 2} }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "minProperties": 1,"maxProperties": 2} } }' ], + 'Empty array with minProperties: 1 and maxProperties: 2' => [ + 'input' => '{ + "value": [] + }', + 'schema' => '{ + "properties": { + "value": {"minProperties": 1,"maxProperties": 2} + } + }', + 'checkMode' => Constraint::CHECK_MODE_NORMAL, + ], + 'Array with two items with maxProperties: 1' => [ + 'input' => '{ + "value": [1, 2] + }', + 'schema' => '{ + "properties": { + "value": {"maxProperties": 1} + } + }' + ], ]; } @@ -72,20 +95,20 @@ public function getValidTests(): array public function getInvalidTests(): array { return [ - [ - '{ + 'Empty object with minProperties: 1' => [ + 'input' => '{ "value": {} }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "minProperties": 1} } }' ], - [ - '{}', - '{ + 'Empty object with minProperties' => [ + 'input' => '{}', + 'schema' => '{ "type": "object", "properties": { "propertyOne": { @@ -98,41 +121,31 @@ public function getInvalidTests(): array "minProperties": 1 }' ], - [ - '{ + 'Object with two properties with maxProperties: 1' => [ + 'input' => '{ "value": { "propertyOne": "valueOne", "propertyTwo": "valueTwo" } }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "maxProperties": 1} } }' ], - [ - '{ + 'Object with two properties with minProperties: 1 and maxProperties: 2' => [ + 'input' => '{ "value": {"foo": 1, "bar": 2, "baz": 3} }', - '{ + 'schema' => '{ "type": "object", "properties": { "value": {"type": "object", "minProperties": 1,"maxProperties": 2} } }' ], - [ - '{ - "value": [] - }', - '{ - "properties": { - "value": {"minProperties": 1,"maxProperties": 2} - } - }' - ], ]; } }