Skip to content
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

OneOf Validation removes validations, making invalid data appear valid #653

Closed
kamtschatka opened this issue Feb 8, 2023 · 7 comments
Closed

Comments

@kamtschatka
Copy link

We are working on validating an array of different kinds of events, that are distinguished by an "event.type" property.
For a reproducer, I have recreated it with a "pet_type" property.
There is the type Cat and Dog. If I just put them as possible types into the array, the passed in JSON gets validated against each type separately and we will get all validation errors for all types, which makes the error very hard to find.
To narrow it down, we are using "if/then/else" to narrow down the type based on the "pet_type" beforehand:

{
	"title": "PetArray",
	"type": "object",
	"properties": {
		"pets": {
			"type": "array",
			"items": {
				"oneOf": [
					{
						"if": {
							"properties": {
								"pet_type": {
									"const": "Cat"
								}
							}
						},
						"then": {
							"type": "object",
							"properties": {
								"hunts": {
									"type": "boolean"
								},
								"age": {
									"type": "integer"
								}
							},
							"required": [
								"age"
							]
						},
						"else": false
					},
					{
						"if": {
							"properties": {
								"pet_type": {
									"const": "Dog"
								}
							}
						},
						"then": {
							"type": "object",
							"properties": {
								"bark": {
									"type": "boolean"
								},
								"breed": {
									"type": "string"
								}
							},
							"required": [
								"bark"
							]
						},
						"else": false
					}
				]
			}
		}
	},
	"additionalProperties": false,
	"required": [
		"pets"
	]
}

I then pass in this JSON for validations:

{
	"pets": [
      {
       "pet_type": "Cat",
        "hunts": "asdf",
        "additionaValue": "asdf"
      }
    ]
}

What I expect it to complain about:

  • "hunts" is a string and not a boolean
  • "age" is missing completely
  • optional: "it also does not match the "false" condition at the end

When I run this on https://www.jsonschemavalidator.net/, everything shows up as expected.

When I run it with the json-schema-validator, the only message I get is "Boolean schema false is not valid". This is basically the optional error I have listed above.

When I debug through the validator, I can see that the "OneOfValidator" actually detects the problem with the "age" property being required, when it is missing. The validation error gets filtered out in the OneOfValidator though, because of #535.

The problem with "hunts" being a string and not a boolean is also detected and filtered out, but I did not debug into it further.

In my opinion the change for issue 535 is invalid and should be removed again. The JSON does not match against either of the provided schemas, so all the errors should be shown. https://www.jsonschemavalidator.net shows the same outcome as json-schema-validator showed before the change.

To get a better validation result for the sample from issue 535, the "if/then/else" mechanism should probably be used.

@stevehu
Copy link
Contributor

stevehu commented Mar 26, 2023

@kamtschatka I have reviewed the changes for #535 and the fix makes sense. Could you please elaborate a little bit more on what was wrong with that PR? Or better yet, summit a PR to help the discussion? Thanks.

@kamtschatka
Copy link
Author

The fix only makes sense for this particular use case, and only because the schema in the sample for #535 is not created properly.
The basic issue was that the validator did not narrow down the validation, because the schema did not tell it to do so.

The schema said the following:
It must either be of type 1 or 2. When the passed in event did not match the description for either one of the types, it showed the error messages for both of them (which is also what https://www.jsonschemavalidator.net/ does and what I would expect)

What you can however do is the following:
If the schema has property 1 then it MUST be of type 1 and therefore the validation needs to only perform validations for type 1 and not show validation errors for type 2

This change for #535 tries to perform some magic in the validations to narrow it down(which is not actually specified in the schema definiton), which breaks the validation results for other scenarios.

@stevehu
Copy link
Contributor

stevehu commented Mar 26, 2023

I am with you. We shouldn't have customized code to handle a particular scenario. Is it possible for you to submit a PR to get it fixed? Thanks.

@fdutton
Copy link
Contributor

fdutton commented Apr 20, 2023

@kamtschatka Do these messages meet your needs?

"validationMessages": [
"$.pets[0]: should be valid to one and only one schema, but 0 are valid",
"$.pets[0].age: is missing but it is required",
"Boolean schema false is not valid"
]

@kamtschatka
Copy link
Author

kamtschatka commented Apr 20, 2023

The first 2 look good, but I am wondering why the third one is there? The "false" condition is part of the else branch, so shouldn't it be omittted?
Edit: just realized it is from the other validation. Looks good to me.

@fdutton
Copy link
Contributor

fdutton commented Apr 20, 2023

I updated the OneOfValidator; I still have to tackle the IfValidator. If this is good for you, I'll close this issue. It would be nice if you reported another issue on what you expect from if-then-else validation.

@fdutton
Copy link
Contributor

fdutton commented May 1, 2023

Closing as resolved

@fdutton fdutton closed this as completed May 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants