-
Notifications
You must be signed in to change notification settings - Fork 356
oneOf never validates when one item is array type the other is scalar or null when checkMode = Constraint::CHECK_MODE_COERCE_TYPES #770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for the report I'll try and find time to take a look soon. Do you perhaps also know if this occurs with earlier versions as well? |
I have migrated from "5.2.13" to "6.0.0". I've been using 5.2.13 with custom TypeConstraint class:
Mime TypeConstraint was almost the same as there is now in the project except mine version did not have array coercion. |
I think I'm running into this same issue. The following unit test passes with version 5.3 but fails with version 6.0: <?php
namespace Tests\Unit\Validation;
use JsonSchema\Constraints\Constraint;
use JsonSchema\Validator;
use PHPUnit\Framework\TestCase;
class JsonValidateV6Test extends TestCase
{
public function testJsonCompare()
{
$schema = <<<JSON
{
"title": "Location",
"type": "object",
"properties": {
"id": {
"type": "string"
},
"related_locations": {
"oneOf": [
{
"type": "null"
},
{
"type": "array",
"items": {
"type": "object",
"properties": {
"latitude": {
"type": "string"
},
"longitude": {
"type": "string"
}
}
}
}
]
}
}
}
JSON;
$json = <<<JSON
{
"id": "LOC1",
"related_locations": [
{
"latitude": "51.047598",
"longitude": "3.729943"
}
]
}
JSON;
$jsonObj = json_decode($json);
$schemaObj = json_decode($schema);
$jsonSchemaValidation = new Validator();
$jsonSchemaValidation->validate($jsonObj, $schemaObj, Constraint::CHECK_MODE_COERCE_TYPES);
$this->assertTrue($jsonSchemaValidation->isValid());
}
} |
@jozefbriss I've been looking into this report and quickly realised that your schema combined with the type coercion is working against each other. Simple put, your schema defines This makes the schema invalidate because for the In earlier version your case was valid but with the improvements made in #384 the type coercion was extended to also include arrays. This is part of @madman-81 something similar applies for you as well. Combining
After the change the second subschema is checked which is now no longer valid due to the changes made by the first subschema. This might be actually a true problem as the second subschema should be checked against the original data not the version altered by the first subschema. Perhaps the following could already resolve the issue of the first sub schema altering the value causing the second sub schema to be invalid for the changed data diff --git a/src/JsonSchema/Constraints/UndefinedConstraint.php b/src/JsonSchema/Constraints/UndefinedConstraint.php
index 4d955cf..caa0341 100644
--- a/src/JsonSchema/Constraints/UndefinedConstraint.php
+++ b/src/JsonSchema/Constraints/UndefinedConstraint.php
@@ -352,14 +352,17 @@ class UndefinedConstraint extends Constraint
if (isset($schema->oneOf)) {
$allErrors = [];
- $matchedSchemas = 0;
+ $matchedSchemas = [];
$startErrors = $this->getErrors();
+ $originalValue = $value;
+
foreach ($schema->oneOf as $oneOf) {
+ $originalValue = $value;
try {
$this->errors = [];
- $this->checkUndefined($value, $oneOf, $path, $i);
+ $this->checkUndefined($originalValue, $oneOf, $path, $i);
if (count($this->getErrors()) == 0) {
- $matchedSchemas++;
+ $matchedSchemas[] = ['schema' => $oneOf, 'value' => $originalValue];
}
$allErrors = array_merge($allErrors, array_values($this->getErrors()));
} catch (ValidationException $e) {
@@ -367,10 +370,12 @@ class UndefinedConstraint extends Constraint
// other schema options in the OneOf field.
}
}
- if ($matchedSchemas !== 1) {
+
+ if (count($matchedSchemas) !== 1) {
$this->addErrors(array_merge($allErrors, $startErrors));
$this->addError(ConstraintError::ONE_OF(), $path);
} else {
+ $value = $originalValue;
$this->errors = $startErrors;
}
}
|
@DannyvdSluijs Thank You. I have switched to Further, specification of inner type for array from the example did not fix the problem. Simply It seems type coercion and A possible improvement could be to do two passes through |
That could be done however that would have some negative impact on the performance. I think for now using the anyOf is best. |
It seems that coercing scalar to array causes than oneOf never validates when one item is array type and the other is scalar or null.
The reason is that any scalar or null can be coerced to array.
Maybe there should not be toArray coercion.
results in:
version: 6.0.0
Maybe the issues is more generic than only related to array and "oneOf" and Constraint::CHECK_MODE_COERCE_TYPES may not work together.
The text was updated successfully, but these errors were encountered: