-
-
Notifications
You must be signed in to change notification settings - Fork 311
schema.json mandates infinite recursion via $ref #263
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
The spec says nothing about actually adding defaults into data, so there is no contradiction in the spec itself. If you do add defaults, you can indeed cause infinite recursion in this case. The way I am resolving this issue in ajv is that even if validator instance has the option that enables insertion of defaults, this option does not apply to meta-schemas (that are usually recursive) as you probably do not want to mutate your schemas anyway. |
I've read a bit more, and found out that so this is probably something that will need to be resolved if/when a "apply_default_on_validation" keyword is added |
Thanks all - sounds like it's woolly enough we'll have to come up with our own sane middle ground for how to deal with them until the spec nails down the intended behavior more precisely. @epoberezkin: I like your meta-schema idea, but how do you identify whether something is a meta-schema? As far as I'm aware, there's no attribute that says whether a schema is intended for validating other schemas. How do you deal with non-meta schemas that still define infinite recursion? |
@erayd I don't see how you end up in an infinite loop here, even by adding an validating defaults. If I understand you correctly, you are filling in the default value for But that's not how validation works. Validation is also a function of the instance. If you are validating an array, and But then you stop. You don't just keep stuffing infinitely many layers of Plus, an implementation should notice that a schema of |
@handrews In the case I'm talking about, and as per my example code above, It's quite possible that I'm missing something fundamental (in which case, I'd really appreciate it if someone explained it a bit differently, because I'm not grasping it so far) - but unless I'm missing something, the only way to avoid infinite recursion here is to be inconsistent about how default values are handled, or to not validate default values. I get that the spec is not particularly well defined in this area, but surely if it deliberately intended that
You're assuming that I don't want to validate whatever default value I just used in place of
Why do you stop? The spec certainly doesn't say to stop. Shouldn't it be the case that, when deciding whether or not to validate defaults, that decision is universal and consistent? Otherwise you could easily end up in the situation where your default value is a template, which itself contains other defaults, and those defaults are never expanded. Yes, there are a number of ways to break such a loop - but shouldn't it be reasonable to assume the following?
At the end of the day, it's the combination of those two assumptions with the way the spec defines |
You stop because the validation outcome of If you blindly expand every possible validation keyword in every empty object, of course it is infinite recursion. It's a recursive schema. But that's ignoring that you do not need to do any such thing to produce a validation outcome. The specification directive:
is telling you that if it is possible for you to detect a terminating condition for recursion, then you MUST do so in order to be a conforming implementation. There are many possible schemas that are clear terminating conditions, but So if you automatically write in every default to infinite levels, you are in violation of the spec. Not because of the specification of |
@handrews Does the spec violate the "Schemas SHOULD NOT make use of infinite recursive nesting like this, the behavior is undefined" bit of that same paragraph, or is it considered to be fine because the behavior of
It's not. For example,
There are many, many use-cases where clamping an input to be valid against a schema, including filling of missing values, is useful (e.g. part of a webservice that accepts user input, validates it and adds missing values, then takes some action based on the resulting document). Simply saying "you don't need to do this, so don't" is a cop-out. In addition, the act of validating the default is where the issue lies, not whether or not that value is applied to the input - you cannot answer the validation question completely without also determining whether the defaults are valid. Is there a recommended position to take on how deeply defaults should be applied, when default-applying is happening? It sounds like inconsistent behavior is mandated by the schema, based on the bit you quoted above - but it doesn't take any position on what that inconsistent behavior should be. Is applying defaults, but not defaults-on-defaults, a reasonable position to take? It has the upside of being simple to implement, but the downside of causing unexpanded templates. |
My point with a schema of So whenever you see a schema of As for applying defaults, that is not a concern of the spec as it is written. If you want to make use of a default value in an application, it is up to you to do so in a way that makes sense. If you want a well-specified mechanism for applying default values in APIs, well, I'd tell you to comment on the issue for it but I got fed up with people dragging it horribly off-topic in the replies and closed it. I'll file it again eventually after draft 06 is published and I'll try to remember to mention you in it. Please don't try to further convince us that "default" is problematic to use. We know. There are multiple issues filed. There will be more. If you want more background, you can find my email in the spec document, feel free to email me and I'll go into more detail. |
@erayd And I meant look at the spec document on master to find my email, not the published one :-) I'm going to go ahead and close this because we already have #204 to cover the general problem with To be clear, you are identifying real concerns here, it's just a very messy area and we're more focused on getting Draft 06 out the door right now than diving into big new topics. That's why #204 is holding where it is. Hopefully we'll have Draft 06 out in the next few weeks and can start looking at bigger concerns again. |
Gotcha - that sounds essentially like your position agrees with the 'don't apply defaults inside defaults' solution I asked about above, so I will implement it in that manner for now. Thanks for clarifying :-). More background would certainly be useful, but I suspect that my wanting to know more background to the issue is more of a curiosity thing than my genuinely needing to know it - I'll ask, but if you're busy, please feel free to decline further explanation. I'll keep an eye on #204 and see where it goes - have subscribed to updates on that issue. The only case I can think of that doesn't seem to immediately cover is that it would be useful to be able to use nested defaults values to achieve essentially the schema equivalent of inheritance - but that's definitely not essential. I appreciate the time you spent on this issue - thank you :-). |
If the following three points are all true:
items
is not set; andThen the result is infinite recursion:
items
is not setitems
to an empty objectschema.json excerpt:
The official spec document here says:
The validation document here says:
My understanding from reading the above is that if
default
is used in accordance with the spec, and validated as recommended, thenschema.json
violates the no-infinite-recursion-via-$ref rule.I am currently trying to resolve this issue in a validator library (see here) - have I badly misunderstood things here, and / or is there a recommended way of dealing with the situation?
The text was updated successfully, but these errors were encountered: