-
-
Notifications
You must be signed in to change notification settings - Fork 223
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
dereference() fails to deference circular ref #37
Comments
When I first read your bug report, I agreed with your expected behavior. In fact, I was shocked that such an obvious bug had existed for so long in JSON Schema $Ref Parser. 😱 But then I created a quick test to make sure, and that's when I realized that the current behavior is actually correct, and it's actually the same thing as your expected behavior. Effectively, your example schema equates to this: schema.properties.foo = schema.properties.foo; So, de-referencing the schema is effectively a no-op and has no effect. The |
@BigstickCarpet Thanks for the quick response! Reading through the JSON-Schema and JSON-Pointer specs, the behavior for this case does not seems to be well specified. However, the way json-schema-ref-parser currently handles this case can lead to a cascade of unresolved $refs, and seems somewhat internally inconsistent: // 1. case in this issue (A -> A, silent failure):
{
properties: {
foo: { $ref: '#/properties/foo' }
}
} => {
properties: {
foo: { $ref: '#/properties/foo' }
}
}
// 2. related case (A -> B -> B, silent failure):
{
properties: {
foo: { $ref: '#/properties/bar' },
bar: { $ref: '#/properties/bar' }
}
} => {
properties: {
foo: { $ref: '#/properties/bar' },
bar: { $ref: '#/properties/bar' }
}
}
// 3. related case (A -> B -> A, stack overflow):
{
properties: {
foo: { $ref: '#/properties/bar' },
bar: { $ref: '#/properties/foo' }
}
} => [Stack Overflow]
// 4. related case (A -> B, C -> A, ok):
{
properties: {
foo: { $ref: '#/properties/bar' },
bar: { properties: { baz: { $ref: '#/properties/foo' }}}
}
} => {
properties: {
foo: [Ref to bar],
bar: { properties: { baz: [Ref to foo] }}
}
} A couple of options come to mind:
What do you think? |
Thanks for all the example cases. I'll add them to the test suite. I think your question basically comes down to how a self-referencing 1) The $ref resolves to itselfThis is the current behavior, which is basically a no-op. The Pros:
Cons:
2) The $ref resolves to an empty objectI think this is the behavior that you're suggesting (please correct me if I'm wrong). Pros:
Cons:
|
Thanks for the writeup. My vote is for (2). I'm not sure it's less correct than (1), since the behavior is unspecified, and as you noted, if we go with (1) then downstream software must always handle the case of unresolved $refs. In any case, it seems that behavior would need to be updated for my 3rd example above. I would defer to people closer to the spec. @handrews @dlax @awwright would one of you mind chiming in? |
For this kind of self-reference, a parser MUST NOT get stuck in an infinite loop (so the stack overflow case is a bug in terms of implementing the schema), but aside from that the behavior is explicitly undefined. Schema authors SHOULD NOT produce such schemas: https://tools.ietf.org/html/draft-wright-json-schema-01#section-8
Do you have a use case for this self-reference? I can't figure out how it would ever be used, but perhaps I'm missing something? |
Agreed. @epoberezkin Does ajv do anything about this? |
@handrews Thanks for the comment. I do not have a valid use case, and it also seems like an error case to me. For my application (https://github.com/bcherny/json-schema-to-typescript), I could either catch these types of cycles in the validation phase (hopefully deferring to json-schema-ref-parser), or be lenient and compile to empty objects. It was not clear to me what the right approach is, so I am deferring to @BigstickCarpet and everyone else in this thread. |
@BigstickCarpet What do you think? Any chance you'll have time to resolve this in the near future? |
Were I using the program, I'd rather it error out because writing such a schema is almost certainly a mistake, or at best a misunderstanding of how the schema is supposed to work. Then again I generally prefer fail-fast over tolerance in machine communication (unlike, say, HTML, where a human can probably make sense of a best effort interpretation of malformed HTML anyway). |
@handrews I agree! As long as traces/error messages are good, fail fast is almost certainly more helpful than silently correcting the user's input. |
+1 on what @handrews said about what the behavior should be, and that self referencing doesn't really make much sense. FWIW the test suite does not currently cover circular references, simply because at the moment it has no way of representing the expected outcome (that nothing loops forever), but that was also not really explicitly in the spec before. |
I should point out too, JSON Schema doesn't use JSON Reference (draft-pbryan-zyp-json-ref-03) anymore -- the expression is only allowed where a schema is expected, now. And there's probably no good reason to ever have an infinite loop/a reference back to yourself, that should probably be a fatal error. JSON Reference was removed because there's no way to have references without at least somewhat understanding the semantics of the JSON Schema document: It only made sense to have the reference in a place where a schema is expected, you have to know if that schema descends into an instance or not (items/properties vs. allOf/anyOf/oneOf) if you're going to handle infinite loops as a fatal error, and you need to know the current URI base. |
@bcherny - I will get started on this soon (hopefully this week), depending on how busy I am at work. I believe the stack overflow bug is already fixed in the 4.0 branch. But I'll also address the reference-to-self problem. |
I think based on lack of everyones time and lack of interest from other people this is going to have to be closed. It's been almost 4 years. If anyone who's struggling with this problem can contribute with a pull request, that would be really appreciated! |
Hi!
I'm using json-schema-ref-parser to power ref resolution in https://github.com/bcherny/json-schema-to-typescript. Thank you for the great work - it makes my life much easier.
I am running into an issue with circular $refs. Here is the simplest repro case:
Input:
Output (actual):
Output (expected):
This is likely related to #36.
The text was updated successfully, but these errors were encountered: