-
-
Notifications
You must be signed in to change notification settings - Fork 292
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
ambiguous behaviour of additionalProperties when invalid #1172
Comments
That sounds like the issue raised in json-schema-org/community#57 and addressed for the next interim release in #1154. |
I’m wondering if we read json-schema-org/community#57 incorrectly.
I read this as, the |
@Relequestual If I understand your point correctly, you are saying that Consider the following schema: {
"properties": {
"foo": true,
"bar": false
}
} That schema has the following subschemas:
So at this point, based on the following:
We infer that
Following the same logic:
So one way to read this:
is the following: applicators may define extra annotations than the sum of their subschemas, but must emit nothing if the applicator does not validate successfully. However, what about Therefore, an applicator seems to have a way to aggregate annotations from their subschemas, even if some fail. It follows that However, there is still a key difference between |
I think |
@Relequestual Actually, I think the issue reported here is valid.
The |
So, again I come back to...
In the defintiion of "Validation succeeds if, for each name that appears in both the instance and as a name within this keyword's value, the child instance for that name successfully validates against the corresponding schema." In contrast, here is "An instance validates successfully against this keyword if it validates successfully against all schemas defined by this keyword's value." It may seem like clutching at straws, and you COULD argue that |
…ut existence see json-schema-org/json-schema-spec#1172 and #collaborators thread
… evaluating see ttps://github.com/json-schema-org/json-schema-spec/issues/1172
This is what I'm a bit confused about. The spec says:
The Furthermore, the section that defines
The above section mentions "validation succeeds if" (making it also sound like an assertion), and the final line says "Omitting this keyword has the same assertion behavior as an empty object" which implies that the presence of I understand your point that |
I think the categorization of a keyword into a single bucket is wrong. I address this in my opening comment on json-schema-org/community#63 (section on annotations). |
I think the spec explicitly mentions that keywords can fall within multiple categories:
|
I'm sorry @Relequestual, but that doesn't make sense. Applicators assert on the result of applying one or more schemas. For Here's an example. Let me know if I understand your interpretation correctly. {
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"additionalProperties": false
} {
"foo": 42,
"bar": "hello"
} This schema has three keywords at the top level: Under the current interpretation, both "foo" and "bar" would both be considered additional instead of just "foo" because Under the draft-07 interpretation, nothing is considered additional and I still have to think a little more about how the new interpretation would affect |
I think under the new interpretation, it would report
|
From what I understand from this thread, if we agree that
|
With the new interpretation, all keywords produce annotations (the ones that produce them, anyway), whether asserting |
Edited transcription of my analysis and discoveries from slack: At first I thought @Relequestual was wrong but now I'm not so sure :) If this interpretation is (to be) correct, then additionalProperties behaves the same whether annotations are supported or not, at least.. and unevaluatedProperties will no longer evaluate at properties that were evaluated (but with an error in the subschema) via adjacent properties and patternProperties - which was the other part of my "I don't like how annotations work here" complaint, but required a change in behaviour for the next draft.
This would now mean that this:
would now only produce one error instead of two. which is different than if we did:
.. which is not a bad thing really - a reference being replaced with the subschema it represents I ran the acceptance tests against updated code -- there is one change in behaviour, at unevaluatedItems.json: "unevaluatedItems depends on adjacent contains" - "contains passes, second item is not evaluated". This is where there is a "contains" keyword that does not validate against an item. the test is written presuming that unevaluatedItems will evaluate at this location (and fail); if we change the use of an adjacent contains to prevent unevaluatedItems from doing anything, then the overall validation result is different. An equivalent test for "unevaluatedProperties" isn't possible because there is no equivalent for "contains" -- if "properties" produced a true result, then it annotates, and unevaluatedProperties would not evaluate there; if it produced a false result, the overall result is still false whether or not unevaluatedProperties does anything. Once again "contains" is a problem child! :) The diff is here (it's small!) -- https://github.com/karenetheridge/JSON-Schema-Modern/compare/ether/unevaluated-respects-local-evaluation?expand=1 ..later.. hmm, actually that's only part of the necessary change. I'm not yet accounting for annotations from adjacent applicators that failed overall but still produced some annotations (and all applicators need to be updated here - allOf,anyOf,oneOf, not (!!!), too. And making this change actually simplifies a lot of code. e.g. previously in "allOf", I had to save the new annotations (from subschemas) to a different list and then decide whether to append them onto the master list or not. now I can just append them directly, and let the next higher scope decide whether to copy what it received and append to its master list ..later.. ok, second commit added, that was straightforward. I'm still in favour of this change. even though it requires changing one test in the acceptance suite 🙂 the test suite is not authoritative; the spec is; we have found and fixed errors in the tests before. |
I think the change to (Grasping at straws here) |
Why? The spec is very clear that "evaluated" means "successfully evaluated". The spec says that the annotation result for
Either you're missing the point or I am. As I understand it, in the current interpretation, if the Consider these two schemas. {
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"unevaluatedProperties": false
} {
"allOf": [
{
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
}
}
],
"unevaluatedProperties": false
} With instance {
"foo": 42,
"bar": "hello"
} Under the current interpretation, both schemas assert that "foo" and "bar" are unevaluated. The successful evaluation of "bar" is dropped because the
I don't see why this behavior should change with the new interpretation. The @Relequestual |
Yes. This actually let me remove a fair bit of code (the second commit referenced in my diff above) because applicator keywords no longer need to accumulate their subschemas' annotations in a separate list (previously they would keep the new annotations separate, until after all subschemas were evaluated and we'd know if the keyword was going to produce a valid or invalid result). Now we only need to maintain separate annotation accrual at the overall subschema evaluation level - after all keywords in that subschema have evaluated, then we decide whether to throw those new annotations away or forward them on to the previous level of evaluation recursion. |
The important difference in interpretation is whether an invalid keyword allows adjacent keywords to see the annotations produced by its subschemas or not. If annotations are not wiped out until after all adjacent keywords have been evaluated, then those annotations can be used by other keywords when considering whether to evaluate at a certain property/item or not. I just realized there will still be a difference in "do we evaluate at this property or not" in the case of boolean schemas -- draft7
It depends on whether we are just changing the way annotations are preserved within subschemas, or also changing the interpretation of "evaluated". I made the "evaluated" change first, and then the annotation-preservation change second; given the second change, the first change is rendered somewhat redundant, except for contains, and in the case of boolean schemas I described above. Let's look more closely at the test case... The schema is:
The data is:
Now, under an interpretation of "evaluated means a subschema was applied at this location, no matter whether it returned a valid or invalid result", unevaluatedItems would not evaluate at index 1, because contains already evaluated there, producing an overall result of true. However, this means that unevaluatedItems never has an effect when used in combination with contains (whether adjacent to it in the same schema, or in another schema elsewhere that is applied to the same data location). I can see arguments both ways as to whether this is useful or not: If we only alter our interpretation to allow for how annotations are handled in subschemas, and do not change our interpretation of "evaluated means evaluated even if not successfully", then:
On the other hand, if we also alter our interpretation of evaluated to mean "evaluated means evaluated even if not successfully", then the changes I propose in #1154 are moot, and also this one I'm not yet sure which one of these I prefer. I believe that option #1 could be done now, in the interim draft revision, but #2 is a bigger change and would might a new draft, as it produces actual changes in overall validation results (as shown in the |
A far as I can tell, @Relequestual is only suggesting that the spec says something different about annotation collection than we thought it did. I don't think he's also suggesting that we misinterpreted what "evaluated" means. Given the wording in the spec, I think the former is a reasonable question to ask, but the latter is clearly wrong. I think the last example I presented clearly shows that the new interpretation is problematic and not what was intended. I think that for the patch release it's reasonable to change the spec to reflect the intention and what everyone interpreted it to mean. If we want to change what "evaluated" means, we can do that in the next full release, but we need to decide what to do for the patch release first. |
This isn't quite right.
which could be interpreted to mean "the properties it declares." With this,
Where is this? I can't find it. There are, however, many places where the spec explicitly states "successfully evaluated" or "evaluated successfully," implying that "evaluated" just means "looked at." Moreover, these phrases are concentrated around the section for the I think that we're good with this new interpretation without any changes. If anything, I'd just want further clarification around stopping annotations at the schema boundary and retaining all annotations within the context of a subschema (regardless of pass/fail of a particular keyword) until that subschema has completed evaluation. |
I don't know how you come to this conclusion. If "evaluated" just meant "looked at", why would it need to say "successfully"? "Evaluate" is used as a more generic term for "validate". I can say that with authority because I came up with that word. So, you should read it as "successfully evaluated" and "validated successfully". I'm surprised this point is controversial. It was discussed in depth. It was a counterintuitive concept, but Henry successfully convinced almost everyone that that was how |
That may be, but it doesn't change that the spec is full of places where it explicitly states successful or unsuccessful evaluation/validation. Reading the spec, it's not defined with a successful outcome as the default.
Because if that was what "evaluated' meant, the spec would need to specify the result, which it does. If "evaluated" means "successfully validated," then "evaluated successfully" is redundant. Regardless, I think this is tangential given the definitions I listed above. |
I updated my library (still haven't published yet) to always add annotations at the keyword level, whether the keyword itself passes or fails. It made no difference to the overall outcome: I still passed the test suite. It did, however, have an impact on the set of errors I returned. This is the error set that my users expect to see. The superfluous |
I'm a bit confused by this, because I thought in this thread that we brought clarity to what is being said in the specification (and more than one of us in this thread were wrong with their original understanding of what it said). Specifically, what we found is this:
Therefore the original premise for this (#1172) issue is moot, and we can either do nothing, or insert some clarifying wording in the documentation regarding when annotations are propagated/not propagated to containing schemas, and specifically pointing out that applicator keywords can produce/propagate both errors and annotations at the same time. |
This is the direction I'd like to go. In which case, none of this matters. |
I'm happy to do that, too, but not in a patch to this version of the spec. Let's open a new issue to discuss that for the next one. |
I mostly agree. I suggested an alternate interpritation to understanding annotation propagation. However I'm not convinced that if we DO take that interpritation, that we won't be inadvertintly creating problems elsewhere. We can ask at least two implementations (@karenetheridge and @gregsdennis 's) to check in terms of validaiton. We can also ask to confirm if there are implications for the annotation and output format results (aka, does running the test suite result in different output based on the changed understanding). But, what concerns me is that we don't have an output test suite. It's possible there are changes in annotations and output that we wouldn't see by running the validaiton test suite alone. I'm caucious about allowing through a change when I don't feel we can truly assess the impact. Given we plan to re-evaluate the annotations process as a whole for the next version, it feels a little counter producitve to spend cycles to allow us to confidently make a change which we plan to make moot soon after.
Indeed. Nothing in terms of the spec, but we must at a minimum add a CREF acknowledging the problem.
...If we choose to accept the new interpritation of annotation propogation. As I said, I don't feel we can fully evaluate the impact. (I'd love to be convinced I'm wrong about this).
As earlier...
We can do this within a CREF. Doing so would explicitly not change the specification. You, and others, would be free to make an interpritation of your choosing regards to annotation propagation because the spec is lacking (Hence why we're still on this issue 😅). As an aside: Looking at
"...subschema is applied... produces an annotation result... indicating all items have been evaluated against My concern remains though, that as we missed the intent, we may have allowed changes which are impacted by the different interpritations. |
After discussions on Slack...
As such, I'll move forward with a PR to do just that (adding a CREF) looking to resolve this issue. |
Fixes json-schema-org#1172 Must see new issue relating to the behaviour of annotation collection for resolving in the next draft.
JsonSchema.Net (testable on https://json-everything.net/json-schema) has been updated to use the new interpretation. I had four separate issues opened with people requesting this adjustment, but I had declined saying that keywords that failed validation don't pass along annotations. This reinterpretation has allowed me to fulfill their requests. |
Fixes json-schema-org#1172 Must see new issue relating to the behaviour of annotation collection for resolving in the next draft.
Fixes #1172 Must see new issue relating to the behaviour of annotation collection for resolving in the next draft.
Given that:
I'll close this issue as resolved. |
Fixes #1172 Must see new issue relating to the behaviour of annotation collection for resolving in the next draft.
This cuts down on the number of errors when `UnevaluatedProperties` fails. Related: - #157 - json-schema-org/json-schema-spec#1172
This cuts down on the number of errors when `UnevaluatedProperties` fails. Related: - #157 - json-schema-org/json-schema-spec#1172
This cuts down on the number of errors when `unevaluatedProperties` fails. Related: - #157 - json-schema-org/json-schema-spec#1172
This uses all adjacent (same schema) results to calculate unevaluated keys/items, whether the keywords validated successfully or not. Previously, it only considered valid results, which causes confusing errors: ```ruby schemer = JSONSchemer.schema({ 'properties' => { 'x' => { 'type' => 'integer' } }, 'unevaluatedProperties' => false }) schemer.validate({ 'x' => 'invalid' }).map { _1.fetch_values('schema_pointer', 'error') } # => # [["/properties/x", "value at `/x` is not an integer"], # ["/unevaluatedProperties", "value at `/x` does not match schema"]] ``` The overall validation result shouldn't be affected, since the only additional keywords that it considers are failed ones (meaning the entire schema fails regardless of the unevaluated keys/items). Duplicate/unhelpful error messages are reduced, though, which is the main reason for making this change. Generally, this interpretation doesn't align with my reading of the spec, but there's been a lot of [discussion][0] around it and I think it makes sense from a user experience perspective. Hopefully it will get clarified in a future draft. Closes: #157 Related: - json-schema-org/json-schema-spec#1172 - https://github.com/orgs/json-schema-org/discussions/67 - https://github.com/orgs/json-schema-org/discussions/57 - https://github.com/json-schema-org/json-schema-spec/blob/2cb7c7447f9b795c9940710bf0eda966a92c937f/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md [0]: json-schema-org/json-schema-spec#1172
This uses all adjacent (same schema) results to calculate unevaluated keys/items, whether the keywords validated successfully or not. Previously, it only considered valid results, which causes confusing errors: ```ruby schemer = JSONSchemer.schema({ 'properties' => { 'x' => { 'type' => 'integer' } }, 'unevaluatedProperties' => false }) schemer.validate({ 'x' => 'invalid' }).map { _1.fetch_values('schema_pointer', 'error') } # => # [["/properties/x", "value at `/x` is not an integer"], # ["/unevaluatedProperties", "value at `/x` does not match schema"]] ``` The overall validation result shouldn't be affected, since the only additional keywords that it considers are failed ones (meaning the entire schema fails regardless of the unevaluated keys/items). Duplicate/unhelpful error messages are reduced, though, which is the main reason for making this change. Generally, this interpretation doesn't align with my reading of the spec, but there's been a lot of [discussion][0] around it and I think it makes sense from a user experience perspective. Hopefully it will get clarified in a future draft. Closes: #157 Related: - json-schema-org/json-schema-spec#1172 - https://github.com/orgs/json-schema-org/discussions/67 - https://github.com/orgs/json-schema-org/discussions/57 - https://github.com/json-schema-org/json-schema-spec/blob/2cb7c7447f9b795c9940710bf0eda966a92c937f/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md [0]: json-schema-org/json-schema-spec#1172
This uses all adjacent (same schema) results to calculate unevaluated keys/items, whether the keywords validated successfully or not. Previously, it only considered valid results, which causes confusing errors: ```ruby schemer = JSONSchemer.schema({ 'properties' => { 'x' => { 'type' => 'integer' } }, 'unevaluatedProperties' => false }) schemer.validate({ 'x' => 'invalid' }).map { _1.fetch_values('schema_pointer', 'error') } # => # [["/properties/x", "value at `/x` is not an integer"], # ["/unevaluatedProperties", "value at `/x` does not match schema"]] ``` The overall validation result shouldn't be affected, since the only additional keywords that it considers are failed ones (meaning the entire schema fails regardless of the unevaluated keys/items). Duplicate/unhelpful error messages are reduced, though, which is the main reason for making this change. Generally, this interpretation doesn't align with my reading of the spec, but there's been a lot of [discussion][0] around it and I think it makes sense from a user experience perspective. Hopefully it will get clarified in a future draft. Closes: #157 Related: - json-schema-org/json-schema-spec#1172 - https://github.com/orgs/json-schema-org/discussions/67 - https://github.com/orgs/json-schema-org/discussions/57 - https://github.com/json-schema-org/json-schema-spec/blob/2cb7c7447f9b795c9940710bf0eda966a92c937f/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md [0]: json-schema-org/json-schema-spec#1172
This uses all adjacent (same schema) results to calculate unevaluated keys/items, whether the keywords validated successfully or not. Previously, it only considered valid results, which causes confusing errors: ```ruby schemer = JSONSchemer.schema({ 'properties' => { 'x' => { 'type' => 'integer' } }, 'unevaluatedProperties' => false }) schemer.validate({ 'x' => 'invalid' }).map { _1.fetch_values('schema_pointer', 'error') } # => # [["/properties/x", "value at `/x` is not an integer"], # ["/unevaluatedProperties", "value at `/x` does not match schema"]] ``` The overall validation result shouldn't be affected, since the only additional keywords that it considers are failed ones (meaning the entire schema fails regardless of the unevaluated keys/items). Duplicate/unhelpful error messages are reduced, though, which is the main reason for making this change. Generally, this interpretation doesn't align with my reading of the spec, but there's been a lot of [discussion][0] around it and I think it makes sense from a user experience perspective. Hopefully it will get clarified in a future draft. Closes: #157 Related: - json-schema-org/json-schema-spec#1172 - https://github.com/orgs/json-schema-org/discussions/67 - https://github.com/orgs/json-schema-org/discussions/57 - https://github.com/json-schema-org/json-schema-spec/blob/2cb7c7447f9b795c9940710bf0eda966a92c937f/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md [0]: json-schema-org/json-schema-spec#1172
This uses all adjacent (same schema) results to calculate unevaluated keys/items, whether the keywords validated successfully or not. Previously, it only considered valid results, which causes confusing errors: ```ruby schemer = JSONSchemer.schema({ 'properties' => { 'x' => { 'type' => 'integer' } }, 'unevaluatedProperties' => false }) schemer.validate({ 'x' => 'invalid' }).map { _1.fetch_values('schema_pointer', 'error') } # => # [["/properties/x", "value at `/x` is not an integer"], # ["/unevaluatedProperties", "value at `/x` does not match schema"]] ``` The overall validation result shouldn't be affected, since the only additional keywords that it considers are failed ones (meaning the entire schema fails regardless of the unevaluated keys/items). Duplicate/unhelpful error messages are reduced, though, which is the main reason for making this change. Generally, this interpretation doesn't align with my reading of the spec, but there's been a lot of [discussion][0] around it and I think it makes sense from a user experience perspective. Hopefully it will get clarified in a future draft. Closes: #157 Related: - json-schema-org/json-schema-spec#1172 - https://github.com/orgs/json-schema-org/discussions/67 - https://github.com/orgs/json-schema-org/discussions/57 - https://github.com/json-schema-org/json-schema-spec/blob/2cb7c7447f9b795c9940710bf0eda966a92c937f/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md [0]: json-schema-org/json-schema-spec#1172
I was testing a schema and getting an additionalProperties error that didn't make much sense to me as the name of the property was in the schema.
So I put together a smaller schema to reproduce it.
I tried testing it against this piece of json.
I tried it against a few of the online validators and depending on which implementation I tried the errors that I would get are different, sometimes I would just get the error about
test
not being a string, other times I would also get an error about no additional properties.Reading http://json-schema.org/understanding-json-schema/reference/object.html#additional-properties
Specifically around
properties whose names are not listed in the properties keyword or match any of the regular expressions in the patternProperties keyword
implies that only the property name is important, not if it's valid or not.I know that some of these implementations use annotations in order to determine if a property is additional or not, and those annotations will get dropped if any properties are invalid as referenced here, which is probably why I'm seeing what I am.
#939
Is there any expectations as to how additionalProperties is meant to work in these instances?
The text was updated successfully, but these errors were encountered: