You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c686e65
Browse filesBrowse the repository at this point in the historyBrowse files
docs: document reference escaping, writing and version conversion (#64)
- references: local references are JSON pointers in a URI, so "/" and "~"
in a key are escaped as "~1" and "~0", and the pointer is percent-decoded;
add how references are written, including inlining references whose
target the written document does not have.
- version conversion: list which references stay references and which are
written inline, how V2 channel references map to V3 channel keys, and the
operations and messages a downgrade drops.
- README: drop the JsonPointer.Net attribution, which is no longer a
dependency, and fix the ReferenceResolutionSetting name and a server
reference example.
Copy file name to clipboardExpand all lines: README.md
+2-3Lines changed: 2 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -129,13 +129,13 @@ All readers will write warnings and errors to the diagnostics.
129
129
130
130
131
131
## Reference Resolution
132
-
Internal references are resolved by default. This includes component and non-component references e.g `#/components/messages/MyMessage` and `#/servers/0`.
132
+
Internal references are resolved by default. This includes component and non-component references e.g `#/components/messages/MyMessage` and `#/servers/production`.
133
133
External references can be resolved by setting `ReferenceResolution` to `ResolveAllReferences`.
134
134
The default implementation will resolve anything prefixed with `file://`, `http://` & `https://`, however a custom implementation can be made, by inhereting from the `IStreamLoader` interface and setting the `ExternalReferenceLoader` in the `AsyncApiReaderSettings`.
135
135
External references are always force converted to Json during resolution. This means that both yaml and json is supported - but not other serialization languages.
Copy file name to clipboardExpand all lines: website/docs/guides/references.mdx
+24Lines changed: 24 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -61,6 +61,10 @@ The V2 server fields are `url` and `protocol`; the host is not serialized as `ht
61
61
62
62
Internal references are resolved by default during document reading. This covers component references such as `#/components/servers/shared` and document locations outside components, such as `#/servers/production`. The reference object remains a typed proxy: its target properties can be read directly, while `Reference.Reference` retains the URI and `UnresolvedReference` reports whether the target was found.
63
63
64
+
A local reference is a JSON pointer ([RFC 6901](https://www.rfc-editor.org/rfc/rfc6901)) into the document, so it can point at any location, not only at components: for example `#/channels/userSignup/messages/signedUp` or `#/servers/production/variables/port`. A key that contains `/` or `~` must be escaped as `~1` or `~0`. A channel keyed `user/signedup` is referenced as `#/channels/user~1signedup`; the unescaped `#/channels/user/signedup` points at a `signedup` member inside a `user` channel instead, and does not resolve.
65
+
66
+
Because a reference is a URI, its pointer is also percent-decoded before it is evaluated. `#/servers/a%20b` and `#/servers/a b` both refer to a server keyed `a b`, and resolve to the same server. A key that contains `%` itself must encode it as `%25`: a server keyed `a%20b` is referenced as `#/servers/a%2520b`. References the library writes for such keys, for example when converting between versions, are percent-encoded the same way.
67
+
64
68
Reference resolution is part of reading a full document with `Read`; `ReadFragment<T>` parses a fragment but does not run the document reference-resolution pass. A missing or invalid internal target is reported in diagnostics and remains unresolved.
65
69
66
70
```csharp
@@ -96,6 +100,26 @@ if (production is AsyncApiServerReference serverReference)
96
100
97
101
Consumers can often read a resolved proxy as the referenced type without first copying or replacing it. Keep the reference-type and resolution checks when your code requires a concrete target. For an unresolved reference, proxy getters can return `null`; avoid relying on target properties until `UnresolvedReference` is false. Reader errors and warnings are returned in `diagnostics`.
98
102
103
+
## Write references
104
+
105
+
References are written as references, including ones whose target could not be resolved, so they are not lost. To write local references as their target instead, set `ReferenceInline` on the writer settings. External references are always written as references. With `InlineReferences`, a local reference that cannot be resolved throws an `AsyncApiWriterException`.
A reference to a location the written document does not contain is written inline, even without `InlineReferences`. This happens when converting between versions: a 2.x reference to `#/channels/userSignup/publish/message` has no equivalent location in 3.x, and a 3.x reference to `#/operations/sendUserSignup/traits/0` has none in 2.x. References that still resolve in the written document, such as references to components or servers, stay references. AsyncAPI 2.x cannot reference tags or external documentation, so those are written inline when writing 2.x. See [version conversion](./version-conversion) for the other differences.
122
+
99
123
## External references
100
124
101
125
`AsyncApiReaderSettings.ReferenceResolution` defaults to `ReferenceResolutionSetting.ResolveInternalReferences`: local references are resolved and external references remain unresolved placeholders. Set `ResolveAllReferences` to load external references too. The built-in loader supports absolute `file://`, `http://`, and `https://` URIs. Relative external URIs require a `BaseUri`; the built-in loader resolves them relative to that URI as file paths. Other URI schemes require a custom loader.
Copy file name to clipboardExpand all lines: website/docs/guides/version-conversion.mdx
+14-1Lines changed: 14 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -22,6 +22,19 @@ var outputV3 = document.SerializeAsJson(AsyncApiVersion.AsyncApi3_0);
22
22
23
23
`AsyncApi3_0` is the API's V3 selector; the current V3 writer emits `asyncapi: 3.1.0`.
24
24
25
-
The serializer maps between the different version shapes, but a round trip is not guaranteed to preserve every representation detail. To bridge the versions, references may be moved, rewritten, or represented differently while keeping the specification's behavior as close as possible. V3-only model information cannot survive a downgrade when V2 has no corresponding field. In particular, channel keys may be normalized as addresses; generated operation keys can use `anonymous-operation-{int}` when no operation ID is available; operation IDs are not retained through a V2 downgrade; and when a V2 shape supports only one message in a location, only the first message is selected. References may also be reflowed or resolved during conversion.
25
+
The serializer maps between the different version shapes, but a round trip is not guaranteed to preserve every representation detail. To bridge the versions, references may be moved, rewritten, or represented differently while keeping the specification's behavior as close as possible. V3-only model information cannot survive a downgrade when V2 has no corresponding field. In particular, channel keys may be normalized as addresses; generated operation keys can use `anonymous-operation-{int}` when no operation ID is available; operation IDs are not retained through a V2 downgrade; and when a V2 shape supports only one message in a location, only the first message is selected. V2 has one `publish` and one `subscribe` operation per channel, so a downgrade drops further V3 operations with the same action on a channel. V2 messages only exist inside operations, so a V3 message that no operation uses is not written.
26
26
27
27
Review converted output when round-trip fidelity matters, especially around removed fields, operation identifiers, multiple messages, and references. See the [AsyncAPI migration guide](https://www.asyncapi.com/docs/migration/migrating-to-v3) for specification-level changes.
28
+
29
+
## References
30
+
31
+
References that resolve in the written version stay references, such as references to components (`#/components/messages/userSignedUp`) or servers (`#/servers/production`). A reference to a location that does not exist in the written version is written inline instead:
32
+
33
+
- V2 references into `publish` or `subscribe` operations, such as `#/channels/userSignup/publish/message`, have no V3 location.
34
+
- V3 references into `#/operations/...` have no V2 location.
35
+
- V3 writes component schemas as Multi Format Schema Objects, so a reference into a schema, such as `#/components/schemas/User/properties/id`, has no V3 location.
36
+
- V2 writes message headers as their schema, and cannot reference tags or external documentation, so those are written inline in V2.
37
+
38
+
V2 keys channels by address, and the reader normalizes the address into the V3 channel key. A V2 reference to another channel, such as `#/channels/user~1signedup`, is read as `#/channels/usersignedup`, and is written back by address in V2.
39
+
40
+
See [references](./references#write-references) for how references are written in general.
0 commit comments