-
-
Notifications
You must be signed in to change notification settings - Fork 0
References and Reference Resolution
References are handled through specific reference types. When adding references to a document it must be done using the proper reference uri
Adding a server component reference could be done like so.
var document = new AsyncApiDocument
{
Info = new AsyncApiInfo
{
Title = "MyDocument",
},
Servers = new Dictionary<string, AsyncApiServer>
{
{ "server1", new AsyncApiServerReference("#/components/servers/myServer") },
},
Components = new AsyncApiComponents
{
Servers = new Dictionary<string, AsyncApiServer>
{
{
"myServer", new AsyncApiServer
{
Host = "example.com",
Protocol = "https",
}
},
},
},
};
var yaml = document.SerializeAsYaml(AsyncApiVersion.AsyncApi2_0);
The above yields the following yaml
asyncapi: 2.6.0
info:
title: MyDocument
servers:
server1:
$ref: '#/components/servers/myServer'
components:
servers:
myServer:
url: https://example.com
protocol:
References created programmatically are NOT resolved until (de)serialization, meaning that de-referencing will not work. De-referencering only works on documents coming from a reader.
We can see the dereferencing in action using the following test
// The document model
var document = new AsyncApiDocument
{
Info = new AsyncApiInfo
{
Title = "MyDocument",
},
Servers = new Dictionary<string, AsyncApiServer>
{
{ "server1", new AsyncApiServerReference("#/components/servers/myServer") },
},
Components = new AsyncApiComponents
{
Servers = new Dictionary<string, AsyncApiServer>
{
{
"myServer", new AsyncApiServer
{
Host = "example.com",
Protocol = "https",
}
},
},
},
};
// Serialize to yaml v3
var yaml = document.SerializeAsYaml(AsyncApiVersion.AsyncApi3_0);
// deserialize (like we would with ingress specifications)
var doc = new AsyncApiStringReader().Read(yaml, out var diagnostics);
var resolvedReference = doc.Servers.First().Value;
// Dereferencing due to reference resolution happening during deserialization.
Assert.AreEqual("example.com", resolvedReference.Host);
Assert.AreEqual(true, resolvedReference is AsyncApiServerReference);
Assert.AreEqual(false, ((AsyncApiServerReference)resolvedReference).UnresolvedReference);
Assert.AreEqual("#/components/servers/myServer", ((AsyncApiServerReference)resolvedReference).Reference.Reference);
As you'll notice form the first Assertion, the consumer does not have to care (much), whether its a reference or not as we dereference the resolved reference directly (even for multiple levels of references). However, in some cases (where a reference is not required) it might be nice to check whether it is a reference, and whether it has been resolved or not. Particularly with external references, if they arent resolved, due to error or otherwise you might hit some null refs.
Reference resolution only happens when deserializing from a specification.
Internal references are resolved by default.
This includes component and non-component references e.g #/components/messages/MyMessage
and #/servers/0
.
External references can be resolved by setting ReferenceResolution
to ResolveAllReferences
.
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
.
External references are always force converted to Json during resolution.
This means that both yaml and json is supported - but not other serialization languages.
var settings = new AsyncApiReaderSettings { ReferenceResolution = ReferenceResolution.ResolveAllReferences };
var document = new AsyncApiStringReader(settings).Read(json, out var diagnostics);
Reference resolution can be disabled by setting ReferenceResolution
to DoNotResolveReferences
.