From 465a947cc924efc831f00411ae41ed6240df8080 Mon Sep 17 00:00:00 2001 From: Erayd Date: Fri, 17 Mar 2017 14:28:44 +1300 Subject: [PATCH 1/4] Allow the schema to be an associative array Implements #388. --- src/JsonSchema/Constraints/BaseConstraint.php | 19 +++++++++ src/JsonSchema/Validator.php | 5 +++ tests/ValidatorTest.php | 42 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 tests/ValidatorTest.php diff --git a/src/JsonSchema/Constraints/BaseConstraint.php b/src/JsonSchema/Constraints/BaseConstraint.php index bc608f6d..b0fe8933 100644 --- a/src/JsonSchema/Constraints/BaseConstraint.php +++ b/src/JsonSchema/Constraints/BaseConstraint.php @@ -10,6 +10,7 @@ namespace JsonSchema\Constraints; use JsonSchema\ConstraintError; +use JsonSchema\Constraints\TypeCheck\LooseTypeCheck; use JsonSchema\Entity\JsonPointer; use JsonSchema\Exception\ValidationException; @@ -89,4 +90,22 @@ public function reset() { $this->errors = array(); } + + /** + * Recursively cast an associative array to an object + * + * @param array $array + * + * @return object + */ + public static function arrayToObjectRecursive($array) + { + foreach ($array as &$value) { + if (is_array($value)) { + $value = self::arrayToObjectRecursive($value); + } + } + + return LooseTypeCheck::isObject($array) ? (object) $array : $array; + } } diff --git a/src/JsonSchema/Validator.php b/src/JsonSchema/Validator.php index d479103c..0a9a8418 100644 --- a/src/JsonSchema/Validator.php +++ b/src/JsonSchema/Validator.php @@ -40,6 +40,11 @@ public function validate(&$value, $schema = null, $checkMode = null) // reset errors prior to validation $this->reset(); + // make sure $schema is an object + if (is_array($schema)) { + $schema = self::arrayToObjectRecursive($schema); + } + // set checkMode $initialCheckMode = $this->factory->getConfig(); if ($checkMode !== null) { diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php new file mode 100644 index 00000000..a75ccecc --- /dev/null +++ b/tests/ValidatorTest.php @@ -0,0 +1,42 @@ +validate($data, $schema); + + $this->assertFalse($validator->isValid(), 'Validation succeeded, but should have failed.'); + } + + public function testCheck() + { + $schema = json_decode('{"type":"string"}'); + $data = json_decode('42'); + + $validator = new Validator(); + $validator->check($data, $schema); + + $this->assertFalse($validator->isValid(), 'Validation succeeded, but should have failed.'); + } + + public function testCoerce() + { + $schema = json_decode('{"type":"integer"}'); + $data = json_decode('"42"'); + + $validator = new Validator(); + $validator->coerce($data, $schema); + + $this->assertTrue($validator->isValid(), 'Validation failed, but should have succeeded.'); + } +} From 869d003b168760dc701c6328533d509a5c62d49b Mon Sep 17 00:00:00 2001 From: Erayd Date: Mon, 20 Mar 2017 10:20:53 +1300 Subject: [PATCH 2/4] Use json_decode(json_encode()) for array -> object cast --- src/JsonSchema/Constraints/BaseConstraint.php | 12 ++++++++---- tests/ValidatorTest.php | 11 +++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/JsonSchema/Constraints/BaseConstraint.php b/src/JsonSchema/Constraints/BaseConstraint.php index b0fe8933..951f2fd2 100644 --- a/src/JsonSchema/Constraints/BaseConstraint.php +++ b/src/JsonSchema/Constraints/BaseConstraint.php @@ -12,6 +12,7 @@ use JsonSchema\ConstraintError; use JsonSchema\Constraints\TypeCheck\LooseTypeCheck; use JsonSchema\Entity\JsonPointer; +use JsonSchema\Exception\InvalidArgumentException; use JsonSchema\Exception\ValidationException; /** @@ -100,12 +101,15 @@ public function reset() */ public static function arrayToObjectRecursive($array) { - foreach ($array as &$value) { - if (is_array($value)) { - $value = self::arrayToObjectRecursive($value); + $json = json_encode($array); + if (json_last_error() !== \JSON_ERROR_NONE) { + $message = 'Unable to encode schema array as JSON'; + if (version_compare(phpversion(), '5.5.0', '>=')) { + $message .= ': ' . json_last_error_msg(); } + throw new InvalidArgumentException($message); } - return LooseTypeCheck::isObject($array) ? (object) $array : $array; + return json_decode($json); } } diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index a75ccecc..6125d4cb 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -18,6 +18,17 @@ public function testValidateWithAssocSchema() $this->assertFalse($validator->isValid(), 'Validation succeeded, but should have failed.'); } + public function testBadAssocSchemaInput() + { + $schema = array('propertyOne' => fopen('php://stdout', 'w')); + $data = json_decode('{"propertyOne":[42]}', true); + + $validator = new Validator(); + + $this->setExpectedException('\JsonSchema\Exception\InvalidArgumentException'); + $validator->validate($data, $schema); + } + public function testCheck() { $schema = json_decode('{"type":"string"}'); From 627fbc9b111ad0e71529708217f9343e36e16d84 Mon Sep 17 00:00:00 2001 From: Erayd Date: Mon, 20 Mar 2017 11:23:15 +1300 Subject: [PATCH 3/4] Skip exception check on PHP versions < 5.5.0 --- tests/ValidatorTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 6125d4cb..071cc531 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -20,6 +20,9 @@ public function testValidateWithAssocSchema() public function testBadAssocSchemaInput() { + if (version_compare(phpversion(), '5.5.0', '<')) { + $this->markTestSkipped('PHP versions < 5.5.0 trigger an error on json_encode issues'); + } $schema = array('propertyOne' => fopen('php://stdout', 'w')); $data = json_decode('{"propertyOne":[42]}', true); From 665e974eaa5627f26eb9ecd739f362c971428de6 Mon Sep 17 00:00:00 2001 From: Erayd Date: Mon, 20 Mar 2017 11:33:03 +1300 Subject: [PATCH 4/4] Skip test on HHVM, as it's happy to encode resources --- tests/ValidatorTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 071cc531..73688537 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -23,6 +23,9 @@ public function testBadAssocSchemaInput() if (version_compare(phpversion(), '5.5.0', '<')) { $this->markTestSkipped('PHP versions < 5.5.0 trigger an error on json_encode issues'); } + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM has no problem with encoding resources'); + } $schema = array('propertyOne' => fopen('php://stdout', 'w')); $data = json_decode('{"propertyOne":[42]}', true);