-
-
Notifications
You must be signed in to change notification settings - Fork 280
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
feat: introduce new schema referencing standard #825
feat: introduce new schema referencing standard #825
Conversation
* feat: merge with latest master * ci: updating spec urls to match new Information Architecture in website (asyncapi#801) * docs: fix links in Markdown files (asyncapi#769) Co-authored-by: Alejandra Quetzalli <[email protected]> Co-authored-by: Khuda Dad Nomani <[email protected]>
Kudos, SonarCloud Quality Gate passed! |
While the "JSON" in "JSON Reference" implies that it would only work for JSON-stored data, that's not actually true as it could very easily be used to reference data in any structured format. Do you have any examples where using a JSON Reference is not sufficient for another structured data format, like Protobuf? I'm not saying that JSON References are the end-all-be-all, but unless you see a limitation I'm not aware, they're pretty powerful and not as language specific as its name may imply. |
I guess I could see where writing a library that was content-aware to swap between resolving in structured language X to structured language Y could be difficult. But I could also see that as being application/domain specific, meaning you could just drive your JSON Reference library manually. |
I would love nothing more if we could stay with JSON Reference or if there exist another standard (xkcd) 😄 Also why I made this draft to trigger those very discussions whether it's even needed, cause just because I see it does not mean that's how it is 😄 So here are my issues with the current standard, and these go back to the requirement for the change:
As JSON pointer, does not define any logic for how to resolve the referenced resource that is non-JSON. The question becomes how you handle it within a JSON document. Do you load the resource and place it into a
I don't read anywhere within JSON Reference that it defines how the implementation can know the type of the referenced resource. How can implementations be content-aware about how to handle the referenced resources?
As the standard is solely targeted JSON data, there is a lot of implies within using the standard for non-JSON data. Even though you probably could force it to comply in some way. As you say "just a hierarchical combination of keys and indices".
For example, while you can use
As you highlight, technically, yes you can utilize fragments, but how exactly? See #216 Those are just the issues I can remember at the moment. One of the core reasons behind authoring it as a standard is that regardless of whether we do it, we need to build tooling to handle references within a multi-spec document. So having this as a standard just makes sense to me 🤷 @whitlockjc what would your suggestion be instead, in terms of how we should move forward to support this requirement of referencing non-JSON data? 🤔 |
I'm not sure JSON Reference cares about the data being resolved, and in my opinion it shouldn't care. Resolution only cares with resolving something, it doesn't care what that something is. And in the case of JSON References, so long as the data is structured, it seems resolvable to me. (I do wonder how one might handle XML though, where you might need to resolve properties vs. nested elements. But I'm sure a simple convention would suffice instead of creating yet another standard or approach.)
Much like the first, the standard doesn't mention this because it doesn't care, and I question whether it should. If you know enough about where the data is, you should be able to reason about what kind of data is there. To me, this is highly specific to the application using the data and I'm not sure if adding complexity so that tooling can "guess" is worth it.
I'm not sure I agree with this because a JSON Pointer is nothing more than a URI, a hierarchical series of steps to find something in a structured document. The same JSON Pointer that could locate something in JSON could be used to find data in a non-JSON data format so long as it's structured. For example,
I'm not sure I have an opinion on this, primarily because each format owns how references are supported/treated. For example, OpenAPI started out with bastardized support for JSON References, then started using native JSON References and now uses JSON Schema's resolution of JSON References which is custom/unique to JSON Schema. But where I'm slightly confused is what you mean by a "multi-spec environment", what is that? If a "multi-spec environment" just refers to storing non-AsyncAPI documents/fragments within the AsyncAPI document, I don't think there is a problem. Reason being is that there is no reason why a JSON Reference outside of the nested spec would need to resolve into the nested spec, nor a JSON Reference in the nested spec needing to resolve outside of itself.
Whether the data is JSON or not, if it's structured the rules are the same. Fragments will address hierarchically from the root of the enclosing document. I really don't think JSON vs. non-JSON changes much because a structured document is hierarchical and plays by the same rules. (Like I mentioned earlier, I could see a case for XML and similar languages to need some sort of convention to differentiate between element properties and nested child elements.) SummaryTo me, so long as the data is structured, JSON References allows a very simple way to define where something is in relationship to a document/structure so that you can resolve it. Sure, mixed data formats adds some complexity and there could even be some sort of edge cases for structured data that has data within a container (XML properties) but since JSON References are really just dict/map/object/... with a singular I will look more into the examples you linked to where we might need something that I'm just not seeing. |
TL;DR:
Apologies if I missed something in this lengthy issue, but I wanted to raise a point that has been sporadically important (and often overlooked) within many JSON Schema / JSON Pointer-related discussion about URIs and fragments:
Technically, even with
(emphasis added) Fragment resolution is controlled by the representation's media type. This is why we (the JSON Schema project) added So, whether you start with
There are several parts of resolving a reference which are governed by different mechanisms, some of which can't be changed by downstream standards.
The modern (2019-09+) JSON Schema behavior can be generalized to "use the result in the same way as the containing object is used", which is essentially delegation. That allows the context to determine the behavior of any adjacent fields in the JSON object. For modern JSON Schema, a reference behaves like any other keyword that produces schema results. ***This means that if AsyncAPI takes a similar approach to modern JSON Schema, then you can reference other schemas as the behavior is defined in terms of the schema result, not the schema syntax. *** As far as the base URI, in practice, an embedded JSON Schema resolves references based on the nearest same-object or parent-object
They are not, it is the responsibility of whoever fetched the resource to know the media type and how to interpret fragments based on that. This means that the application that fetched the resource can also map/reinterpret the resource into a media type that supports the desired fragment behavior. This is the step where AsyncAPI can define behavior, such as how to map XML into a JSON Pointer-friendly media type/data model. |
As mentioned on the v3 spec call, I'd be interested in the tooling implications of this. If developers are trying to parse an AsyncAPI with a standard json parsing lib, what is the behavior? |
That is a totally good point. Most JSON parsers don't support JSON Reference by default. However, tools like json-schema-ref-parser does. It won't support this new referencing standard for non-JSON files, but maybe we could build a parser (also called plugins) for asyncapi files. Otherwise, we would need to build tooling around this. cc @jonaslagoni |
I've actually thought of enabling support for this in json-refs via an option, like an experimental feature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the JSON Reference I-D was abandoned almost a decade ago, and $ref
has since been defined only in the context of JSON Schema, *and (most importantly) since you're diverging from both the separate JSON Reference approach and the JSON Schema $ref
approach, it would make more sense to me to use a different keyword name.
[Avro 1.9.0 schema](https://avro.apache.org/docs/1.9.0/spec.html#schemas) | `application/vnd.apache.avro;version=1.9.0`, `application/vnd.apache.avro+json;version=1.9.0`, `application/vnd.apache.avro+yaml;version=1.9.0` | | ||
[OpenAPI 3.0.0 Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaObject) | `application/vnd.oai.openapi;version=3.0.0`, `application/vnd.oai.openapi+json;version=3.0.0`, `application/vnd.oai.openapi+yaml;version=3.0.0` | | ||
[OpenAPI 3.1.0 Schema Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#schemaObject) | `application/vnd.oai.openapi;version=3.1.0`, `application/vnd.oai.openapi+json;version=3.1.0`, `application/vnd.oai.openapi+yaml;version=3.1.0` | | ||
[JSON Schema draft 2020-12](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00) | `application/schema+json;version=draft-2020-12`, `application/schema+yaml;version=draft-2020-12` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The correct way to specify this is:
application/schema+json;schema=https://json-schema.org/draft/2020-12/schema
(I assume you already know that application/schema+yaml
is not really a thing, and could potentially be registered by someone else - in the meantime, if you use it, it should also use the schema=https://...
parameter.)
### Resolution | ||
If the URI contained in the JSON Reference value is a relative URI, then the base URI resolution MUST be calculated according to [[RFC3986](https://datatracker.ietf.org/doc/html/rfc3986#section-5.2)], [section 5.2](https://datatracker.ietf.org/doc/html/rfc3986#section-5.2). Resolution is performed relative to the referring document. | ||
|
||
If a URI contains a fragment identifier, then the fragment should be resolved per the fragment resolution mechansim of the referrant document. If the representation of the referrant document is JSON, then the fragment identifier SHOULD be interpreted as a [[JSON-Pointer](https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#ref-JSON-Pointer)]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be referencing RFC 6901 for JSON Pointer, not the draft.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @handrews for taking the time to clarify these things! Quite a large chunk to digest which took me and @smoya 4 hours, I really hope we got your point and applied it accurately, if not please do correct us!
Fragment resolution is controlled by the representation's media type.
Have to say this one I missed 🧐 A follow-up question regarding this. Do you see it as a problem that we explicitly define the media type for a reference instead of having it determined when the resource of the URI is resolved?
For example with this proposed standard if you reference the following resource:
{
"referenceFormat": "application/json",
"schema": {
"$ref": "http://example.com/example.json#/example/fragment"
}
}
And during the resolution phase of the http://example.com/example.json
determine the mime-type to be application/schema+json
, how can define such contradicting behaviours then 🤔
***This means that if AsyncAPI takes a similar approach to modern JSON Schema, then you can reference other schemas as the behavior is defined in terms of the schema result, not the schema syntax. ***
Do you mind clearifying this, I dont quite understand what you mean here by the schema result, not the schema syntax
🤔?
As far as the base URI, in practice, an embedded JSON Schema resolves references based on the nearest same-object or parent-object $id, and if none exist, against the base URI of the encapsulating entity (e.g. the AsyncAPI or OpenAPI document's base URI). This means that for OpenAPI 3.1, if you have a $id in your schema, you can reference #/$defs/whatever within that schema object ($defs as a sibling to $id), but you can't reference #/components/schemas/whatever in the containing OAS file without instead doing something like https://example.com/oasfile#/components/schemas/whatever
This is precisely why it might be tough to reuse some OpenAPI Schema objects in AsyncAPI because you might have tied the references up with a base URI defined in OpenAPI because when we then reference the OpenAPI Schema object, that base URI is no longer accessable.
But then again, the same issue might happen with JSON Schema documents I guess... Not really anything we can do about it I guess. We just simply have to be aware it might be a problem for some.
This is the step where AsyncAPI can define behavior, such as how to map XML into a JSON Pointer-friendly media type/data model.
Do you also see that we need to define the behaviour for how you map (for example) XML into JSON structure once resolved? I.e. currently I am just lazy and resolve it into a string and let tooling decide how they want to represent and access it.
I feel like this is a good time to bring in the points @whitlockjc have raised, which is, do you @handrews think that JSON Reference properly align with the requirements (as listed in the PR description)? I know you have quite an extensive knowledge of the different standards that all interact with each other, so I would really appreciate your perspective here if you have the bandwidth for it!
Cause I would rather not have to put work into another standard if what we have is suffecient for the requirements we have.
To me, so long as the data is structured, JSON References allows a very simple way to define where something is in relationship to a document/structure so that you can resolve it. Sure, mixed data formats adds some complexity and there could even be some sort of edge cases for structured data that has data within a container (XML properties) but since JSON References are really just dict/map/object/... with a singular $ref key/property that is itself a URI whose resolution rules are pretty clear, I don't see the need for something more complex or necessarily a short coming in JSON References.
@whitlockjc I see we agree that mixed data formats are complex, but where our ways part is that I want a standard to define that behaviour or at least offer me ways to solve it instead of it being up to the individual interpretation and imagination. Cause there are many ways that structured non-JSON data can be converted, and therefore fragments might end up being miss interpreted.
If a URI contains a fragment identifier, then the fragment should be resolved per the fragment resolution mechansim of the referrant document. If the representation of the referrant document is JSON, then the fragment identifier SHOULD be interpreted as a [[JSON-Pointer](https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#ref-JSON-Pointer)]. | ||
|
||
If it's non-JSON, then fragment MUST be ignored as there are no accurate way to fragment into non-JSON data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a URI contains a fragment identifier, then the fragment should be resolved per the fragment resolution mechansim of the referrant document. If the representation of the referrant document is JSON, then the fragment identifier SHOULD be interpreted as a [[JSON-Pointer](https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#ref-JSON-Pointer)]. | |
If it's non-JSON, then fragment MUST be ignored as there are no accurate way to fragment into non-JSON data. | |
If a URI contains a fragment identifier, then the fragment should be resolved per the fragment resolution mechanism of the referrant document. If the representation of the referrant document is JSON, then the fragment identifier SHOULD be interpreted as a [[JSON-Pointer](https://datatracker.ietf.org/doc/html/draft-pbryan-zyp-json-ref-03#ref-JSON-Pointer)]. | |
Otherwise if the referrant document is not JSON and does not explicitly state a fragment resolution mechanism, then it MUST follow the application fragment resolution mechanism defined for the specific [reference-linking format](#reference-linking-format). |
The difference between this and normal [Reference Object](#referenceObject), is to support linking to non-JSON data, that is otherwise not possible through the Reference Object. As well as defining a behavior for when encountering subsequent references. | ||
|
||
See [schema format](....) for reference-linking formats that is supported and how it's defined. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
##### Fragment resolution for non-JSON ([RFC4627](https://datatracker.ietf.org/doc/html/rfc4627)) | |
This section defines how fragment resolution mechanisms work for specific schema formats that is required by [draft-asyncapi-ref-linking-01#/Resolution](./draft-asyncapi-ref-linking-01.md#/Resolution). | |
###### Avro | |
###### Protobuf | |
###### XSD/XML |
@handrews this change is based on your feedback regarding fragment resolution, do you think this makes sense that each referring standard can implement on their own 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonaslagoni thanks for working through all of this!
do you @handrews think that JSON Reference properly align with the requirements (as listed in the PR description)?
So, I realize that my first big comment goes along with JSON Reference as the starting point, and then I came back later and said "don't do that, it's been abandoned for nearly a decade" - sorry about the mixed messaging. I do think it's better to treat the long-abandoned JSON Reference as an inspiration at most, and not something that can or should be normatively cited.
JSON Pointer (RFC 6901) can be normatively cited, either as "we are using RFC 6901 directly" or "we are using RFC 6901 with the following extensions." For example, JSON Schema at times uses JSON Pointers (not URI fragments, just JSON Pointers) with instance data, which JSON works with through a data model that is defined based on JSON. Which is really what happens whenever you parse JSON and then apply a JSON Pointer: you're not working on the document, you're working on an in-memory representation, which is how most people work with JSON Pointers anyway. It's just such a trivial mapping that no one mentions it.
This brings us to:
Do you see it as a problem that we explicitly define the media type for a reference instead of having it determined when the resource of the URI is resolved?... during the resolution phase of the
http://example.com/example.json
determine the mime-type to beapplication/schema+json
, how can define such contradicting behaviours then 🤔
So, you get a resource and you know it's media type (and I'm guessing with some of these formats, there might not be a proper media type defined for them, but you have some other way of knowing what the format is). Technically, (as I understand it anyway), the correct thing to do is interpret the fragment based on the media type, and if the media type does not allow fragments, or doesn't understand that fragment's syntax, then you just end up with the whole resource.
(this next bit might contradict earlier stuff I said about mapping into a different media type, but this is probably a more solid approach)
JSON Hyper-Schema had this problem, because it was designed to work with application/json
(no fragment syntax defined) and potentially other media types that were even less JSON Pointer-fragment-friendly that we couldn't anticipate.
Whenever we needed to identify a resource by a URI, and then access some part of it that would conveniently be accessed by a JSON Pointer fragment, we instead used a URI that was not allowed to have a fragment, and paired it with a plain JSON Pointer (not encoded in a URI). This is why anchorPointer
is a separate field from anchor
(these URIs apply to the instance).
Actually, I think we don't forbid fragments in hyper-schema's anchor
to leave people the flexibility of either using a fragment syntax if they know it will work, or using a non-fragment JSON Pointer if they aren't sure but know that they'll be able to figure out how to apply the JSON Pointer.
While plain JSON Pointers are also officially defined on JSON documents, JSON Schema works on a data model that is based on JSON so as long as the instance, regardless of its media type, has been mapped into the data model, we can apply a JSON Pointer. Because, really, most code applies JSON Pointers to in-memory parsed JSON data, not the actual document. So we just say "we're using an in-memory structure that looks like what a JSON parser produces, and we apply JSON Pointer to that."
It's less elegant than URI fragments, but it avoids all of the pitfalls of the media-type-defined nature of URI fragments. (We do use JSON Pointer fragments and plain name fragments in JSON Schema's $ref
because it is always pointing to a JSON Schema, and JSON Schema's media type defines both JSON Pointer and plain name fragments).
Do you also see that we need to define the behaviour for how you map (for example) XML into JSON structure once resolved? I.e. currently I am just lazy and resolve it into a string and let tooling decide how they want to represent and access it.
If you go with the non-fragment JSON Pointer approach, then yes you need to define how to map XML (or wahtever) into the JSON data model, so it ends up looking like it could have been parsed from JSON. For some formats that's trivial, for others (including XML) it's ambiguous and you have to make some decisions about what to do.
You can specify that for each significant format, though, and I think a lot of the ones you are using are pretty straightforward to map.
(out of time for now, I'll come back and look at more later, but feel free to ping me if I forget).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is precisely why it might be tough to reuse some OpenAPI Schema objects in AsyncAPI because you might have tied the references up with a base URI defined in OpenAPI because when we then reference the OpenAPI Schema object, that base URI is no longer accessable.
But then again, the same issue might happen with JSON Schema documents I guess... Not really anything we can do about it I guess. We just simply have to be aware it might be a problem for some.
I'm not entirely sure I follow. How is the base URI no longer accessible? If you accessed the OAS document, then shouldn't you be able to read the base URI from it? And if you are accessing JSON Schema documents, those have the standard JSON Schema base URI rules.
If you are handed a Schema Object from an OAS file and do not have access to the OAS file, then I can see how that would be a problem, but this is why for any JSON Schema you want to re-use across multiple contexts, you should set an absolute URI for $id
to ensure that the base URI is defined regardless of context. That's what $id
is for.
JSON References are really just a specialized structure, an object containing a sole
For issue 1, JSON References says that the fragment portion of the URI is a JSON Pointer and that works well for JSON documents but there is nothing to explain how to handle non-JSON documents. My opinion is that JSON Pointers work for nearly all structured data without issue or modification. Where JSON Pointers fall apart are for languages where each "node" in the data structure has information within it, like HTML/XML attributes/properties, and for non-structured data (like protobuf). I feel like our only options here are to create a JSON Pointer replacement that is language agnostic, or we use some convention to fill in the gaps. (For example, we could easily use a For issue 2, this is where I have less of an opinion but I could definitely see a JSON representation generated from almost anything, including Protobuf. The good news is that for many of the types we know we want to work with, the problem could already be solved with off the shelve tooling: All this being said, I would like to know exactly what is wrong with what we have now, and what we're trying to solve. Reason being is because I don't think JSON References as they exist now are far off the mark of what we need, other than the lack of JSON Pointers working for everything we want. |
I realize the "JSON" in "JSON Pointer" and "JSON Reference" implies that the containing document is JSON and the referrant document is JSON. But the structure and syntax of these items are by no means tied to just JSON and there is no reason we can't use what's there as-is regardless of the syntax of the containing/referrant documents. That's the point I'm making. |
The more I think about it, the less I care about it. "JSON *" implies JSON-only and if we are looking to get away from that, to me it looks like rewriting the related JSON-specific drafts/specs and figuring out a way to replace them with a language-agnostic equivalent is the best solution. But I do think we could start that in a much simpler way by using the JSON-specific drafts/specs as a base and using a convention to flesh out what we might eventually bubble up to a draft/spec. |
Reading the specification with no in-depth knowledge, I simply fail to see how this can be interpreted from the standard, do you mind clarifying how and where you read this? 😅 There are numerous places within the standard that explicitly state it has to be JSON, RFC4627, not an arbitrary structure that is not tied to JSON. Abstract defines With a bit of creative freedom, I might agree with you and especially since you have such an in-depth knowledge of it, that you can rather easily simply replace
In my eyes we are, but I might be misunderstanding the term. This standard is nothing more than JSON Reference turned agnostic, which takes care of the first issue with JSON reference not (in my words) allowing referring to non-JSON resources. It does not specifically define how to handle complex fragments but leaves this up to the standard that incorporates it. I.e. fragments are something the AsyncAPI spec (or any other) needs to specifically define, see #825 (comment). Regarding resolvement/conversion of non-JSON structures to JSON I simply defined it as having to be placed into a string. Still not sure about this approach and why it's part of the remaining issues to figure out. I fail to see where we can simplify this any further 🧐 Do you have any suggestions? |
In JSON terms, a JSON Reference is an So if the overall structure of a JSON Reference isn't necessarily unique or specific to JSON, I stand by what I said. In JSON terms, a JSON Pointer is a So if a JSON Pointer is really just a collection of "reference tokens" in a language agnostic format, and the requirement of resolution is a hierarchical data structure, neither of these requirements are unique or specific to JSON and I stand by what I said. At the end of the day, JSON References provide a language agnostic way of defining a reference, despite it having "JSON" in its name. And JSON Pointers provide a language agnostic way of defining the hierarchical collection of reference tokens needed to resolve data in a hierarchical data structure, despite it having "JSON" in its name. |
I've tried to read all the comments and understand them 🤯, but I have some problems with the purpose of the PR itself, because we should specify exactly that this is about the ability to reference the schemas themselves (mainly for message payloads, but we should also allow this for other places where we can use SchemaObject in the AsyncAPI document - include extensions and bindings) not to enable referencing for example Info Object defined in XML (or something like that). Additionally, it has been mentioned a lot here that the JSON Pointer itself is JSON agnostic and could be used for data that does not have a typical JSON structure (but it is possible to transform it to JSON) and then the JSON Pointer could actually be used to pull nested data, well here is the problem because every other structure format (and even JSON-based formats like AVRO) can have (and usually have) a different way of referencing against each other than defined like a JSON Pointer. Another thing, even if we think of a fancy way of referencing other formats and even give it an RFC number, the problem remains: how is this supposed to be supported by the tools themselves? For now, there are no tools that can reference formats other than JSON/Yaml (by JSON Pointer) - XML (whole document from given file) to JSON referencing alone is currently supported in most JSON dereferencing tools and is treated as a plain string, but the problem is nested elements in XML (no mention of attributes, namespaces), so @jessemenning gave a good comment here, because what do we get from spec for referencing as there will be no tools to support it - I don't want to come off as ignorant but is there any implementation (in any language, at least one) that supports 100% all referencing cases (in dereferencing phase) in the new OpenAPI 3.1? If not, why do I need such a possibilities of referencing? Of course, I am also developer and I know that it can be difficult, but at least one tool implementation should be written alongside with given spec or draft for spec to show that's possible. So if we want to somehow incorporate referencing other formats "inside" JSON Pointer, it would have to be strictly defined and explained without relying on any existing tools like XML -> JSON because they don't have to be based on the specification at all but on the author's idea - that is, each tool == a different way of transforming XML to JSON. Simple example with Avro: {
"type": "record",
"namespace": "com.example",
"name": "FullName",
"fields": [
{ "name": "first", "type": "string" },
{ "name": "last", "type": "string" }
]
} and then (inside another Avro schema) I can reference If it were up to me, instead of combining JSON Pointer with other formats, I would prefer a solution like this:
Example: $ref:
link: './avro.avsc'
format: ...avro
type: com.example.FullName As I wrote at the beginning of the post, I tried to understand all the previous comments, but I missed a little bit of such a clue why we are discussing here because we are focusing too much on unimportant things so far, and probably not enough on how it would work in the end and what problems would face the developers of the tools. If I talk nonsense then you can forget about my comment. BTW. Fran mentioned during the discussion of my one proposal about the possibility of defining custom schema formats anywhere in the spec, that probably this possibility is not so important, because anyone can parse XML to JSON and then use a regular JSON Pointer, but it requires a lot of user knowledge and work and we should simplify life. EDIT: What I see in PR's content, Jonas tries to do something similar like my changed $ref but we should conclude how to handled that "fragment content of JSON Pointer". |
Yes, I believe @karenetheridge's OpenAPI::Modern handles all of the cases, using her JSON::Schema::Modern implementation. I think @gregsdennis JSON Everything project either supports it or will soon (he and I talked about base URIs in OAS 3.1 files recently, at least). @jdesrosiers's Hyperjump OAS validator seems to work with the schema objects in isolation, but I'm pretty sure you could use Hyperjump JSON Schema Core to handle references across an OAS 3.1 file as it understands all of the necessary base URI and reference resolution concepts. These are just projects by people I know, and come more out of the JSON Schema side expanding to OAS-specific validation. You may be able to find more for other OAS use cases at openapi.tools. |
Since variations have been brought up by many people in many threads, I'm going to make this plea at the top level: Please, please, please do not make up new
|
Agreed, but didn't JSON Schema do the same? While JSON Schema's syntax is the same as JSON Reference, its resolution behavior is definitely very different than the And that's why I go back to what exactly are we trying to solve here? If you have structured data and a JSON Reference, resolution is possible. While "JSON" is implied by their names, JSON Pointers/References provide a simple syntax and expectation for defining resolution locations and resolution rules...even if you're not using JSON. (JSON References seem to work just fine in YAML for example.) Not looking to rock the boat, but as a long time OpenAPI consumer and tooling author, I'd just hate to see us go down the path of making things harder than they need to be. I'm completely open to changing my mind, I'm just not sure there's been a case made that can't be solved with the existing JSON Reference syntax and resolution rules. Maybe I just missed it above, so I'll go back and re-read again. |
They're all JSON Schema Org specs (including JSON Reference which, like all of the early JSON Schema specs, was edited/authored or co-edited/authored by Kris Zyp), and all clearly marked as drafts. And we talked it over extensively with OpenAPI as you probably recall since you were on a lot of those TSC calls. And there were and are a ton of use cases where keywords alongside It's different when one org redefines another org's specs. We don't redefine JSON Pointer, for example (although we do define Relative JSON Pointer, which is careful not to overlap or contradict JSON Pointer: they are distinct specifications).
The constant stream of people confused about adjacent keywords being ignored and wanting them not ignored indicated that "love" was definitely a stretch. We changed the behavior in response to use cases and confusion within the community. |
First off, there was no disrespect in my message and I never suggested that the decisions made were taken lightly. I do remember being on those OpenAPI TSC calls, but I also remember being one of the people suggesting against the change. My reasons were to avoid confusion for people that know To move on from my original disagreement with the changes to But even if AsyncAPI does this, it does not change my opinion on how |
Thanks, @whitlockjc .
Not to re-litigate but just to explain for those with less context, yes that's a valid concern. But for Reference Objects (which are in OAS 3.1 clearly distinct from Schema Objects- they are never both syntactically valid in the same place) both OpenAPI and AsyncAPI say explicitly in their own documentation that adjacent fields SHALL be ignored. With that restriction, you end up with essentially the same behavior in both places (a
I'm in agreement with you there.
The problem isn't the JSON Pointer part, it's the URI fragment part. All of this boils down to whether one wants to respect the principle that media types determine fragment syntax, and if so how one goes about reconciling that with a varied landscape of data formats, some of which don't define media types, and some of which that do don't define suitable fragment approaches. For anyone wondering where I'm getting this, it's from RFC 3986 §3.5:
That's only a For JSON Schema, |
8805c88
to
624ad52
Compare
A quick update: I have continued to think on the issues brought up here in @jonaslagoni 's proposal, plus the conversation with @whitlockjc and others, including the long-standing use of standalone ref-parsing tools outside of JSON Schema. We are discussing this among the JSON Schema team. It will be a little while before I can share more details due to a team member being OOTO until later this week, but I wanted to let y'all know that my "please don't redefine These sorts of issues have come up periodically, and we're assessing the various proposals that have been considered in the past. I post an update here when I am able, whether that's a new proposal or an acknowledgement that we should work with an existing proposal such as this one (I'm not aware of any other recent proposals, although if anyone knows of any please comment and I'll throw them into the mix). I apologize for being cryptic, it's simply a matter of timing with respect to our team members' schedules. |
A few questions for clarifying requirements. By secondary resource, I more-or-less mean "thing you'd use a fragment to reference if fragment behavior were defined for the media type."
|
Sorry for taking so long folks, had to figure out what we should do with all this information and how to further progress the discussion. Because there are so many things to consider, and use-cases that almost becomes impossible to follow in a PR Therefore I created a dedicated on ONLY focusing on a tooling perspective and how the specifications are sufficient/insufficient in defining expected behavior in order to create a feedback loop to create better standards and tooling. Please see asyncapi/community#485
@magicmatatjahu defined in U8 👍
@magicmatatjahu I am neither against nor for changing the keywords and structure for linking or referencing for that matter, lets see how we can progress that!
@whitlockjc please jump into the discussion in U8 in the discussion, especially as you have the reasons why you see linking to non-JSON resources should be easy to achieve. But remember to point out where exactly in the specifications this is clarified or interpreted! asyncapi/community#485 (comment)
@handrews U9 and U10 might be just for you! This tries to clarify the problem with media types and remote references and media types.
@handrews I hope that the discussion and use cases can help us narrow down exactly where tooling doesn't know what to do because the standards are insufficient and the problems they face. Hope this helps your proposal to narrow it down.
Damn, what a set of questions 😅 Let me see if I can add my perspective to some of them!
I think it could be, see U5, U9, and U10.
I would say that would be preferred, otherwise, implementations can come to the wrong conclusion of what that second resource is, or not even be able to find it.
I would say no here. But I dont have a complete experience with all the standards so I cant possibly say tbh. Maybe #622 can give you some insight.
I would say yes because of #622.
If you take a look at JTD, it uses its own referencing format i.e. simple mapping between reference and definitions. See https://www.rfc-editor.org/rfc/rfc8927#name-ref
Yes, but of course not for all formats.
It is only from a tooling perspective. Because, as far as we can determine, the use-case is not to know it's a reference but what that referenced resource is, so you can iterate/interact with the resolved resourced. Especially when it comes to parsers. |
This pull request has been automatically marked as stale because it has not had recent activity 😴 It will be closed in 120 days if no further activity occurs. To unstale this pull request, add a comment with detailed explanation. There can be many reasons why some specific pull request has no activity. The most probable cause is lack of time, not lack of interest. AsyncAPI Initiative is a Linux Foundation project not owned by a single for-profit company. It is a community-driven initiative ruled under open governance model. Let us figure out together how to push this pull request forward. Connect with us through one of many communication channels we established here. Thank you for your patience ❤️ |
Abstract
The current reference object is no longer sufficient as we need to support non-JSON references, i.e. we can no longer solely rely on JSON Reference. The main problem becomes that AsyncAPI is defined with JSON/YAML and you are referencing something that does not conform to this format. Hence making it though to support. This new standard aims to solve this problem.
Description
This proposal is part of a larger issue, that have been highlighted in multiple GitHub issues, and this PR extends the work from @magicmatatjahu in #797, which this PR is a followup for (to allow referencing non-JSON data structures such as Protobuf, XSD, Avro, FlatBuffer schemas, EDI, COBOL copybook, and the inevitable "cool new format").
This issue is a two parter, cause without tooling, this new standard is use-less.
Requirements for the standard:
Remaining issues/tasks to resolve
$ref
?content
enough?FAQ
Some quick questions and answers about the current state of the standard.
You cannot.
Parsers can, based on the schema format determine whether it has the capability to parse and interpret the reference.
Related issue(s):
Moves schema format into a "schema object" instead of message containing
schema
andschemaFormat
. IntroducingdefaultSchemaFormat
in root AsyncAPI object.schemaFormat
in message object is deprecated/removed. Does look for supporting nested references, i.e. in avro throughschemaRef
that is instead of using URI fragments.Lift the idea of
schemaParse
, which does not make sense as we can look at theschemaFormat
and it's up to the implementation if it supports it.Lift the idea of
$remoteRef
orx-remote-ref
, but that does not make sense either in this setup.Nothing specific, want to reference Flatbuffers.
Proposes
remoteReference
to be unparsable by the parsers and left for generators. Lift the idea ofparse
andremote
. Highlights some requirements:Require clearification how you can utilize JSON Reference and point to non-JSON data.
Require clearification on the following:
A list of possible URI fragments that can be supported for non-JSON data.
Introduce data format bindings, that aim to solve an issue where specific arguments is needed for the schema format.
schemaOptions
being proposed along side #622schemaFormat
behavior in tooling? #656Problem with no clear definition how AsyncAPI parsers can and should handle different
formatSchema
.