-
-
Notifications
You must be signed in to change notification settings - Fork 231
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
"$id" and "$ref" changes in JSON Schema draft 2019-09 and OAS 3.1 #145
Comments
Thank you so much for all the detailed information! Sounds like I have a lot of work ahead of me, but I like the direction that JSON Schema and OpenAPI are heading 👍 |
@handrews - I've started working on implementing JSON Schema 2019-09, and I'd like to know more details about how
I have 2 questions about this. 1) Where is this defined in the spec? 2) How should conflicting values be handled? {
"$defs": {
"field": {
"properties": {
"name": { "type": "string" },
"tabIndex": { "type": "number" },
"value": { "type": "string" }
},
"checkbox": {
"properties": {
"$ref": "#/$defs/field/properties",
"value": { "type": "boolean" }
}
}
}
} In this example, the author most likely intends for the "checkbox" schema to be interpreted like this: {
"properties": {
"name": { "type": "string" },
"tabIndex": { "type": "number" },
"value": { "type": "boolean" }
}
} But if I understand you correctly, the spec intends for the "checkbox" schema to be interpreted like this: {
"properties": {
"value": { "type": "boolean" },
"allOf": [
{
"name": { "type": "string" },
"tabIndex": { "type": "number" },
"value": { "type": "string" }
}
]
}
} Of course, the problem with this interpretation is that the I appreciate any clarification or guidance you can give me. I'm trying to make sure I implement the spec correctly (or as closely as possible) without breaking people's expectations about using |
@JamesMessinger thanks for digging into this! I know it poses more of a challenge for your packages than for most implementations that focus on validation. There are a lot of reasons why The other reasons have to do with a lot of work we did to clarify the processing model for applying a schema to an instance, so that people can make reliable extension keywords that can be done as extensions available across implementations with a reasonable expectation that they will work. The lack of broadly usable extensions has been a huge limiting factor on finalizing JSON Schema, as everyone wants their favorite keyword in the standard. So we needed to be able to say "keyword behaviors are within these boundaries", and supporting merges would have made that much harder. In conforming validators (that handle Fundamentally, JSON Schema is a constraint system, and you can only ever add constraints when you combine schema objects. You cannot remove constraints. Allowing removal would complicate a lot of things. There are other reasons, and well over 500 GitHub comments on the topic. It was a Huge Thing. In fact it was what nearly killed the project after draft-04. So practical advice: Since you are (correct me if I'm wrong) preprocessing JSON files with references, rather than applying schemas, you have more options. I don't know what to do about folks who expect an assertion (like For annotations like You could also add your own keyword that allowed overrides, but it would not ever be a JSON Schema keyword and validators would never handle it correctly. I'd recommend calling it We do expect some challenges as this all gets rolled out to tools that do code generation or other non-instance-based actions, which is why we worked closely with the OpenAPI Technical Steering Committee to see if they thought it would work. Does any of this help? Side note: If you were planning to do anything with |
Thanks for the detailed response. It helped me understand the thinking behind the I really appreciate the tip about |
@JamesMessinger I'm glad it helped! Regarding
When referencing a URI including a plain-name fragment, the behaviors are:
In the special runtime behavior case, if there's a In practical terms: Generally you are given a set of schema resources (which may be 1:1 with a set of files or may have multiple resources per file because of This step is not new- the This is the new part: You want to separately keep track of which resources have When you evaluate a schema with an instance, you do some sort of depth-first traversal of schema, with the exact path of that traversal, and the depth of cycles, determined by the instance. This is because you can't determine the result of a schema object without evaluating all of its subschemas (or, rather, all of the ones that apply to this particular instance). This depth-first traverse defines your dynamic scope. So as you do that traversal, when you descend into a new schema resource, if that resource has a So basically it lets you substitute the same fragment name on a different resource at runtime. This is really useful in recursive meta-schemas. It is not all that useful in other scenarios. When you are done with the resource where you first saw that If you Hopefully this will be really clear in the next draft. I think most of the wording is in, but I'm not sure (it's been a lot of start-stop work with the pandemic and whatnot). But that's a quick overview. |
Interesting comments on #22 related to URIs and
Combining those issues so we can get $id working for JSON Schema 2019-09 and beyond. |
@philsturgeon - This functionality is implemented (for both Draft 4 and 2019-09) in JSON Schema Reader, or, rather, in the internal library that it uses under the hood. The key is that these libraries distinguish between files and resources. A file is a physical file on disk or a URL that has been downloaded, whereas a resource URI identifies a single JSON Schema which may or may not correlate to a single file. This is all documented here.
|
clicks links |
Because unfortunately $RefParser does not support global $ref: APIDevTools/json-schema-ref-parser#145
Hi. Are there any news on this? With the latest lib version and 2020-12 schemas $ref is resolved falsely. {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"native_prop": {}
},
"$ref": "#/$defs/def",
"$defs": {
"def": {
"properties": {
"refed_prop": {}
}
}
}
} Is dereferenced to: {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"native_prop": {}
},
"$defs": {
"def": {
"properties": {
"refed_prop": {}
}
}
}
} While should be: {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"native_prop": {}
},
"allOf": [
{
"properties": {
"refed_prop": {}
}
}
],
"$defs": {
"def": {
"properties": {
"refed_prop": {}
}
}
}
} So $ref should be just replaced with allOf (if schema version is 2019-09 or 2020-12) to conform to the spec. |
Nope, this is not being worked on. As mentioned elsewhere this tool has a misleading name, and is essentially "oas3.0-ref-parser" so its really not geared up for that, and literally nobody involved in maintaining this software has time to rewrite it to support that. Scalar's openapi-parser is promising for OAS3.1 users and onwards, but we are not maintaining a generic JSON Schema tool here. If you'd like to lead the charge on https://github.com/APIDevTools/json-schema-reader/ please let me know and I can set you up. |
JSON Schema draft 2019-09 (formerly known as draft-08) introduced several changes around
$ref
and$id
. This draft is being adopted by the OpenAPI Specification version 3.1.$id
was split into a separate keyword,$anchor
"$id": "#foo"
becomes"$anchor": "foo"
#
as the value of$anchor
is just the name"$ref": "#foo"
or"$ref": "https://example.com/some-schema#foo"
$id
itself MUST resolve to an absolute URI (no fragment)$id
is therefore a full resource with its own URI, even if embedded in another resourcehttps://example.com/some-schema#
, is allowed because it is equivalent to not having a fragment$ref
can now have other keywords beside it$ref
keyword is simply the result of the reference schema{"type": "object", "$ref": "foo"}
is equivalent to{"type": "object", "allOf": [{... contents of foo schema ...}]}
Since this library has not previously supported
"$id": "#foo"
, if you only support one form I would suggest"$anchor": "foo"
since that is where OpenAPI is headed.See also OAI/OpenAPI-Specification#2092 for further details on how this fits into OAS 3.1, as obviously OAS Reference Objects outside of Schema Objects don't know about
allOf
, etc.Feel free to ask questions on the JSON Schema slack. I will also keep an eye on this issue.
The text was updated successfully, but these errors were encountered: