Coder Social home page Coder Social logo

asyncapi / saunter Goto Github PK

View Code? Open in Web Editor NEW
197.0 10.0 55.0 779 KB

Saunter is a code-first AsyncAPI documentation generator for dotnet.

Home Page: https://www.asyncapi.com/

License: MIT License

C# 98.62% HTML 0.60% Dockerfile 0.78%
asyncapi dotnet aspnetcore openapi documentation amqp hacktoberfest

saunter's Introduction

Saunter

CI NuGet Badge

Saunter is an AsyncAPI documentation generator for dotnet.

ℹ Note that pre version 1.0.0, the API is regarded as unstable and breaking changes may be introduced.

Getting Started

See examples/StreetlightsAPI.

  1. Install the Saunter package

    dotnet add package Saunter
    
  2. In the ConfigureServices method of Startup.cs, configure Saunter.

    // Add Saunter to the application services. 
    services.AddAsyncApiSchemaGeneration(options =>
    {
        // Specify example type(s) from assemblies to scan.
        options.AssemblyMarkerTypes = new[] { typeof(StreetlightMessageBus) };
        
        // Build as much (or as little) of the AsyncApi document as you like.
        // Saunter will generate Channels, Operations, Messages, etc, but you
        // may want to specify Info here.
        options.Middleware.UiTitle = "Streetlights API";
        options.AsyncApi = new AsyncApiDocument
        {
            Info = new AsyncApiInfo()
            {
                Title = "Streetlights API",
                Version = "1.0.0",
                Description = "The Smartylighting Streetlights API allows you to remotely manage the city lights.",
                License = new AsyncApiLicense()
                {
                    Name = "Apache 2.0",
                    Url = new("https://www.apache.org/licenses/LICENSE-2.0"),
                }
            },
            Servers =
            {
                ["mosquitto"] = new AsyncApiServer(){ Url = "test.mosquitto.org",  Protocol = "mqtt"},
                ["webapi"] = new AsyncApiServer(){ Url = "localhost:5000",  Protocol = "http"},
            },
        };
    });
  3. Add attributes to your classes which publish or subscribe to messages.

    [AsyncApi] // Tells Saunter to scan this class.
    public class StreetlightMessageBus : IStreetlightMessageBus
    {
        private const string SubscribeLightMeasuredTopic = "subscribe/light/measured";
        
        [Channel(SubscribeLightMeasuredTopic, Servers = new[] { "mosquitto" })]
        [SubscribeOperation(typeof(LightMeasuredEvent), "Light", Summary = "Subscribe to environmental lighting conditions for a particular streetlight.")]
         public void PublishLightMeasuredEvent(Streetlight streetlight, int lumens) {}
  4. Add saunter middleware to host the AsyncApi json document. In the Configure method of Startup.cs:

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapAsyncApiDocuments();
        endpoints.MapAsyncApiUi();
    
        endpoints.MapControllers();
    });
  5. Use the published AsyncApi document:

    // HTTP GET /asyncapi/asyncapi.json
    {
        // Properties from Startup.cs
        "asyncapi": "2.1.0",
        "info": {
            "title": "Streetlights API",
            "version": "1.0.0",
            "description": "The Smartylighting Streetlights API allows you\nto remotely manage the city lights.",
           // ...
        },
        // Properties generated from Attributes
        "channels": {
            "light/measured": {
            "publish": {
                "operationId": "PublishLightMeasuredEvent",
                "summary": "Inform about environmental lighting conditions for a particular streetlight.",
            //...
    }
  6. Use the published AsyncAPI UI:

    AsyncAPI UI

Configuration

See the options source code for detailed info.

Common options are below:

services.AddAsyncApiSchemaGeneration(options =>
{
    options.AssemblyMarkerTypes = new[] { typeof(Startup) };   // Tell Saunter where to scan for your classes.
    
    options.AddChannelFilter<MyAsyncApiChannelFilter>();       // Dynamically update ChanelItems
    options.AddOperationFilter<MyOperationFilter>();           // Dynamically update Operations
    
    options.Middleware.Route = "/asyncapi/asyncapi.json";      // AsyncAPI JSON document URL
    options.Middleware.UiBaseRoute = "/asyncapi/ui/";          // AsyncAPI UI URL
    options.Middleware.UiTitle = "My AsyncAPI Documentation";  // AsyncAPI UI page title
}

Bindings

Bindings are used to describe protocol specific information. These can be added to the AsyncAPI document and then applied to different components by setting the BindingsRef property in the relevant attributes [OperationAttribute], [MessageAttribute], [ChannelAttribute]

// Startup.cs
services.AddAsyncApiSchemaGeneration(options =>
{
    options.AsyncApi = new AsyncApiDocument
    {
        Components = 
        {
            ChannelBindings =
            {
                ["amqpDev"] = new()
                {
                    new AMQPChannelBinding
                    {
                        Is = ChannelType.Queue,
                        Exchange = new()
                        {
                            Name = "example-exchange",
                            Vhost = "/development"
                        }
                    }
                }
            },
            OperationBindings =
            {
                {
                    "postBind",
                    new()
                    {
                        new HttpOperationBinding
                        {
                            Method = "POST",
                            Type = HttpOperationType.Response,
                        }
                    }
                }
            }
        }
    }
});
[Channel("light.measured", BindingsRef = "amqpDev")] // Set the BindingsRef property
public void PublishLightMeasuredEvent(Streetlight streetlight, int lumens) {}
[PublishOperation(typeof(LightMeasuredEvent), "Light", BindingsRef = "postBind")]
public void MeasureLight([FromBody] LightMeasuredEvent lightMeasuredEvent)

Available bindings: https://www.nuget.org/packages/AsyncAPI.NET.Bindings/

Multiple AsyncAPI documents

You can generate multiple AsyncAPI documents by using the ConfigureNamedAsyncApi extension method.

// Startup.cs

// Add Saunter to the application services. 
services.AddAsyncApiSchemaGeneration(options =>
{
    // Specify example type(s) from assemblies to scan.
    options.AssemblyMarkerTypes = new[] {typeof(FooMessageBus)};
}

// Configure one or more named AsyncAPI documents
services.ConfigureNamedAsyncApi("Foo", asyncApi => 
{
    asyncApi.Info = new Info("Foo API", "1.0.0");
    // ...
});

services.ConfigureNamedAsyncApi("Bar", asyncApi => 
{
    asyncApi.Info = new Info("Bar API", "1.0.0");
    // ...
});

Classes need to be decorated with the AsyncApiAttribute specifying the name of the AsyncAPI document.

[AsyncApi("Foo")]
public class FooMessageBus 
{
    // Any channels defined in this class will be added to the "Foo" document
}


[AsyncApi("Bar")]
public class BarMessageBus 
{
    // Any channels defined in this class will be added to the "Bar" document
}

Each document can be accessed by specifying the name in the URL

// GET /asyncapi/foo/asyncapi.json
{
    "info": {
        "title": "Foo API"
    }
}

// GET /asyncapi/bar/asyncapi.json
{
    "info": {
        "title": "Bar API"
    }
}

Migration to LEGO AsyncApi.Net

When switching to the LEGO AsyncApi.Net, we broke the public API.

To simplify the transition to new versions of the library, this note was created.

What was broken:

  • Namespaces have changed:
    • Saunter.AsyncApiSchema.v2 -> LEGO.AsyncAPI.Models
    • Saunter.Attributes; -> Saunter.AttributeProvider.Attributes
  • Change the name of the data structures, add prefix 'AsyncApi' (example 'class Info' -> 'class AsyncApiInfo')
  • All data structure constructors are now with the parameterless constructor

There was no more significant changes on public API.

Keep this in mind when planning the migration process.

Contributing

See our contributing guide.

Feel free to get involved in the project by opening issues, or submitting pull requests.

You can also find me on the AsyncAPI community slack.

Thanks

saunter's People

Contributors

brechtvhb avatar dependabot[bot] avatar devlux avatar filipedguy avatar gomete avatar henryprutsman-situsamc avatar janeggers avatar jellevandendriessche avatar jgpayvision avatar m-wild avatar meunierfrederic avatar ricosuter avatar smoerijf avatar sunnjek avatar tscrypter avatar visualbean avatar wallyuva avatar yurvon-screamo avatar zarusz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

saunter's Issues

Add Kafka bindings

Kafka is a popular message broker.
We should provide

  • classes for Kafka bindings,
  • documentation on how to use Kafka bindings

https://github.com/asyncapi/bindings/tree/master/kafka

Bindings are currently usable by creating a filter which adds the binding.
e.g.

services.AddAsyncApiSchemaGeneration(options =>
{
    options.ChannelItemFilters.Add(new MyAmqpChannelFilter());
}

class MyAmqpChannelFilter : IChannelItemFilter
{
    public void Apply(ChannelItem channelItem, ChannelItemFilterContext context)
    {
        channelItem.Bindings.Amqp = new AmqpChannelBinding
        {
            Is = AmqpChannelBindingIs.RoutingKey,
            Exchange = new AmqpChannelBindingExchange
            {
                Name = "streetlights",
                Type = "topic",
            }
        };
    }
}

Is it possible to add automatically request examples for testing asyncAPI?

Hi evryone,
I wonder, if there is any option to add examples to autogenerated AsyncAPI document. It would be very useful to be able to add them using decorators (swagger-like) to have more complete APIs definitions when importing them into other tools such as Microcks (API listing, mocking and testing tool).
Thanks.

Add HTTP Bindings

HTTP is a popular format for async messaging (webooks).
We should provide

  • classes for HTTP bindings,
  • documentation on how to use HTTP bindings

https://github.com/asyncapi/bindings/tree/master/http

Bindings are currently usable by creating a filter which adds the binding.
e.g.

services.AddAsyncApiSchemaGeneration(options =>
{
    options.ChannelItemFilters.Add(new MyAmqpChannelFilter());
}

class MyAmqpChannelFilter : IChannelItemFilter
{
    public void Apply(ChannelItem channelItem, ChannelItemFilterContext context)
    {
        channelItem.Bindings.Amqp = new AmqpChannelBinding
        {
            Is = AmqpChannelBindingIs.RoutingKey,
            Exchange = new AmqpChannelBindingExchange
            {
                Name = "streetlights",
                Type = "topic",
            }
        };
    }
}

Allow setting description for attributes/parameters

Hi there!

An idea that I think it's not available right now (please correct me if it is). It would be very useful to be able to define the "description" field of the properties of a class via summary or metadata.

Example:

public sealed class MyClass
   {
       /// <summary>
       /// Att1 description.
       /// </summary>
       public double Att1 { get; set; }

       [Saunter.Attributes.ParameterDefinition(Description = "Att2 description.")]
       public double Att2 { get; set; }
   }

Resulting in:

"myClass":{"properties":{
       "Att1":{"type":"number", "description":"Att1 description."},
       "Att2":{"type":"number", "description":"Att2 description."}
}}

SignalR Integration

Hi, from what I can see Saunter doesn't support generating AsyncAPI spec from SignalR hubs out of the box. Do you have any plans to add that? I am willing to give it a try if it's something that you want to add

Add a list of most common server protocols

In order to create the Server object instead of passing a string to the constructor, the list of the most common protocols could be provided to reduce errors and to normalize the casing.

The list is provided in the specs: REQUIRED. The protocol this URL supports for connection. Supported protocol include, but are not limited to: amqp, amqps, http, https, jms, kafka, kafka-secure, mqtt, secure-mqtt, stomp, stomps, ws, wss. (https://www.asyncapi.com/docs/specifications/2.0.0#serversObject).

It is not a limited list.

Use Endpoint routing

Currently, the middleware needs to run in the app pipeline before the terminal Endpoints middleware.

app.UseRouting();

app.UseMiddleware<AsyncApiMiddleware>();
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

It would be nice to register this as an endpoint:

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    endpoints.MapAsyncApiDocuments();
});

Add supported exchange types to the specification

In order to reduce typos, a list of exchange types could be provided as it is a short limited list: The type of the exchange. Can be either topic, direct, fanout, default or headers. (https://github.com/asyncapi/bindings/blob/master/amqp/README.md#channel).

The is property is an enum and this exchange.type seems to be the same case but:

  • I don't know if it could grow or vary more often than is.
  • It will be a breaking change.

So my proposal is to provide a static class with a list of constants just to have the supported options.

align the enum name handling with the behavior of system.text.json

align the enum handling with the behavior of System.Text.Json:

  • use the enum value (int) by default
  • use the case-sensitive name of the enum member if JsonStringEnumConverter is specified

other than that, use the EnumMemberAttribute if the internal EnumMemberConverter is specified

as this behavior is subject to be changed in .NET5 (dotnet/runtime#31081) I would propose to add support for the JsonStringEnumMemberConverter (part of Macross.Json.Extensions) by applying the same logic as with the internal EnumMemberConverter.

requiredmembers not properly setup

the requiredmembers set is not properly assembled: currently any name overrides (jsonpropertyname, datamember) and the propertyselector are not applied on the requiredmembers entries.

Extract serialization from Middleware into Serializer object

Currently the building of the document model is separated from the middleware, and rightfully so. In this way, a third-party application (not necessarily an ASP.NET application) can build the document model independently, either by creating items or by scanning assemblies.

However, the serialization parameters are still in-coded inside the Middleware, meaning that the only way to get a valid JSON output with Saunter is either inside an ASP.NET application using this middleware, or re-implementing the same lines of code elsewhere in a custom tooling.

Extracting the following lines of code into its own AsyncApiDocumentSerializer enables developers that do not wish to use the Middleware on a particular workflow (or cannot because their application is not based on ASP.NET's pipeline) to still generate documentation and serialize it in a pre-configured validatable form. Moreover it enables the ability to plug in multiple different serialization methods (e.g. YamlAsyncApiDocumentSerializer or TextJsonAsyncApiDocumentSerializer).

https://github.com/tehmantra/saunter/blob/07f310f43caba862ad638b09fc071198186bcd77/src/Saunter/AsyncApiMiddleware.cs#L38-L50

Nuget Build

I notice #61 was fixed, are you planning a new nuget build with that in?

Message could be a $ref in Operation.

Check this asyncapi documentation.

channels:
  Envios/Traza/Admision:
    publish:
      operationId: Admision
      message:
        $ref: '#/components/messages/Admision'  

I think is no way to do that with the current classes. The Message should implement an Interface like Schema to have the possibility of add a Reference.

Best Regards,
Facundo

MapAsyncApiDocuments not found

Documentation says that I should add this

app.UseEndpoints(endpoints =>
{
endpoints.MapAsyncApiDocuments();
});

But there is no MapAsyncApiDocuments extension method on v0.2.0 package. I am running .Net 5.

System.Guid apparently not supported

In my many of my classes I have properties of type "System.Guid". This type has itself an Empty property of type "System.Guid". Hence, the component generated by Saunter is:

      "guid":{
            "properties":{
               "Empty":{
                  "$ref":"#/components/schemas/guid"
               }
            }
         }

When I try to render the resulting json file in the AsynApi editor it throws the error "undefined". This could be an infinite loop. Simply setting guid to type string solves the problem, but it is not the desired behaviour.

Maybe I'm doing something wrong?

✨ Feature - MQTTnet.AspNetCore.AttributeRouting Support

I've been struggling to get Saunter v0.3.1 to work in combination with:

My project has these 2 MQTTnet libraries implemented successfully in ASP.NET 5 now.
I tried to follow Saunters documentation to the letter too. However with MQTTnet there was no need for me to implement MessageBus(Interface)s or Event (model-like) classes.

I can send/receive payloads from the MQTTnet.App client test application, however Saunter AsyncAPI Documentation generation keeps failing, the only thing I see hosted under /asyncapi/ui/index.html is the info defined in new AsyncApiDocument() of Startup.cs.

Which lead me to wondering:

  • Are these packages are actually compatible with each other or not?
  • Are any example projects that combine these packages available somewhere? (Looked but couldn't find any)
  • Does Saunter provide a MQTT Broker? (I assume it doesn't, because I saw the mosquitto references, MQTTnet is my Broker that is embedded in the source of my project in this case, thus I have no need for a stand alone broker like mosquitto)

Any help would be truly welcome!

RabbitMQ.Client.Core.DependencyInjection Support

I am currently using RabbitMQ.Client.Core.DependencyInjection so I have all the information in the di container and I dont want to add attributes to all the implementations that contain redundant information.

so what i would like to see is:

public interface IOperationProvider
{
       IEnumerable<(string channelname, Type payloadtype ,OperationType)> ProvideOperations()
}

this lib could provide the default implementation with the code in DocumentGenerator but I would be able to tap into the di container and use the information that is present there.

Herency

Is possible use classes that using herency? I use it to have a basic structure for every event and I add the necessary fields.

public class SyncDocumentIntegrationEvent : IntEvent
{
public int DocumentId { get; }
public int UserId { get; }

    public SyncDocumentIntegrationEvent(int documentId, int userId) : base()
    {
        DocumentId = documentId;
        UserId = userId;
    }
}

The document generated by asyncAPI is enormous and breaks the structure:

I'm doing something wrong?

Thanks for the help.

Missing default property in Schema class.

Another topic. I was using the classes to generate yaml documentation, that is why a found some missing properties.
It will be good to have yaml generation also, What do you think?

Facundo

Add UI to view documentation

Similar to Swachbuckle.AspNetCore which provides app.UseSwaggerUI() it would be nice to have an app.UseAsyncApiUI()

"examples"field is not an Array of Maps

In reference documentation, one can see that Message.examples field is a [Map[string,any]].

However, in Message Class, Examples member is a IDictionary<string,object>.
Generated documentation validation fails (online editor here).

With the following in Message.cs line 42

        [JsonProperty("examples")]
        public IList<IDictionary<string, object>> Examples { get; set; } = new List<IDictionary<string, object>>();

generated documents are valid.

add ability to expose multiple async apis

buhu we have a monolith :)

can you please expose any method to split / filter the api.

for my monster monolith it would be nice to split by first segment of channel name.

right now we write the aync api spec by hand and have:

AcountApi.*
ProductApi.*
.....

but as this is all hosted in one app i now only get a giant doc and i am not able to recreate what we had created manually

Channel Operation should support multiple messages

Currently, Channel is an attribute for a method and the Operation must be an attribute in the same method and only a message type can be provided.

If I repeat the Channel with the same name, on another method, it generates an error indicating the Channel is already added as a key in a Dictionary.

So it's only possible to describe a single Message to one Channel within one Operation.

For example, in my case, I have a Kafka topic that aggregates multiple messages.

In the specification, it describes that in an Operation, a Message Object can be declared as a set of possible message types (using oneOf):
https://www.asyncapi.com/docs/specifications/2.0.0/#operationObject

A possible solution, that is more flexible, is to allow for Channels/Operations and Messages to be declared as independent attributes in multiple classes or methods. In this case, each Message Attribute would specify the Operation it belongs to, and when generating the document, it would update/add the message (stored as a collection) in the specified Operation object.

Thank you for your project and for your help!

datetimeoffset creates recursive schema

"dateTimeOffset":{
"properties":{
"Now":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"UtcNow":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"DateTime":{
"type":"string",
"format":"date-time"
},
"UtcDateTime":{
"type":"string",
"format":"date-time"
},
"LocalDateTime":{
"type":"string",
"format":"date-time"
},
"Date":{
"type":"string",
"format":"date-time"
},
"Day":{
"type":"integer"
},
"DayOfWeek":{
"type":"string",
"enum":[
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
]
},
"DayOfYear":{
"type":"integer"
},
"Hour":{
"type":"integer"
},
"Millisecond":{
"type":"integer"
},
"Minute":{
"type":"integer"
},
"Month":{
"type":"integer"
},
"Offset":{
"type":"string",
"format":"time-span"
},
"Second":{
"type":"integer"
},
"Ticks":{
"type":"integer"
},
"UtcTicks":{
"type":"integer"
},
"TimeOfDay":{
"type":"string",
"format":"time-span"
},
"Year":{
"type":"integer"
},
"MinValue":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"MaxValue":{
"$ref":"#/components/schemas/dateTimeOffset"
},
"UnixEpoch":{
"$ref":"#/components/schemas/dateTimeOffset"
}
}
},

Add channel parameters

Channel parameters field in the specification is an array of parameter objects https://www.asyncapi.com/docs/specifications/2.0.0#parametersObject. In the current implementation, channel parameters field is a string.

There is no way of setting parameters in the ChannelAttibute as Parameters property is a string too.

Could we modify the schema (it is a breaking change) and add a new ChannelParameterAttribute to add one or several parameters to the channel indicated with ChannelAttribute?

Missing character in "ValidRegex" pattern of ComponentFieldName

In my class properties I have some nullable components. In AsyncApiSchema/v2/ComponentFieldName.cs there is a validation of the component field name which does not include the character "`" of my type "nullable`1", which breaks the process.

Just adding the character to ValidRegex fixes the problem:

private const string ValidRegex = @"^[a-zA-Z0-9\.\-_`]+$";

Any collateral damage you could think of after adding this?

Thank you for your work!

the requiredmembers are not properly filled

the requiredmembers set is not properly assembled: currently any name overrides (jsonpropertyname, datamember) and the propertyselector are not applied on the requiredmembers entries.

Create a changelog

  • Create a changelog so that users know what is changing when new versions are published.
  • Follow the keep a changelog format.
  • Add all current versions to the log (currently v0.1.0 and v0.2.0)

Allow oneOf messages

Regarding the AsyncApi specification, the operation field message could be a oneOf with an array of possible message objects.

A definition of the message that will be published or received on this channel. oneOf is allowed here to specify multiple messages, however, a message MUST be valid only against one of the referenced message objects.

The AsyncApi playground supports this case too:
image

Use NJsonSchema for the JSON Schema implementation

Hi Everyone

I'm the maintainer of NSwag (https://github.com/RicoSuter/NSwag) and I have a proposal.

NSwag is built on top of NJsonSchema (https://github.com/RicoSuter/NJsonSchema) which contains the model, schema generator and code generators for JSON Schema.

Would you be open to use NJsonSchema as the base of Saunter? This way you could leverage all the features of NJS and we could bundle our efforts in building great dev tools...

This would probably solve the following issues:

  • #48 NJS supports both Newtonsoft.Json (uses the contract resolver and not reflection for maximum compatibility) and the new System.Text.Json
  • #20 #22 NJS already supports NRT out-of-the-box via https://github.com/RicoSuter/Namotion.Reflection
  • #8 $refs are correctly resolved (document wide) and can be defined in the model (ActualSchema, Reference properties)

What do you think?

A simple spec implementation (simpler than NSwag) based on NJS can be checked out here, eg the spec model just uses the JsonSchema class:
https://github.com/RicoSuter/SigSpec/blob/master/src/SigSpec.Core/SigSpecOperation.cs

/cc @devlux @tehmantra

Add code-first discriminator support

Add discriminator support. It is in the specification and currently, there is no way to mark the polymorphism and inheritance using discriminators.

image

"oneOf" is not part of the schema but it is supported in the AsyncAPI playground:

image

{
  "asyncapi": "2.0.0",
  "info": {
    "title": "Example AsyncAPI",
    "version": "v1"
  },
  "defaultContentType": "application/json",
  "channels": {
    "MessagePublished": {
      "publish": {
        "operationId": "events",
        "message": {
          "payload": { "$ref": "#/components/schemas/event" },
          "name": "event"
        }
      }
    }
  },
  "components": {
    "schemas": {
      "event": {
        "required": ["provider"],
        "discriminator": "provider",
        "oneOf": [
          { "$ref": "#/components/schemas/aEventSubType" },
          { "$ref": "#/components/schemas/otherEventSubType" }
        ]
      },
      "aEventSubType": {
        "required": ["provider", "name"],
        "properties": {
          "provider": {
            "type": "string",
            "description": "aEventSubType."
          },
          "name": {
            "type": "string",
            "description": "aEventSubType name."
          }
        }
      },
      "otherEventSubType": {
        "required": ["provider", "name"],
        "properties": {
          "provider": {
            "type": "string",
            "description": "otherEventSubType."
          },
          "name": {
            "type": "string",
            "description": "otherEventSubType name."
          },
          "additionalProperty": {
            "type": "string",
            "description": "otherEventSubType additionalProperty."
          }
        }
      }
    }
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.