From 74785231c8b894f3411cc4279c0279746f650870 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 12:47:33 -0400 Subject: [PATCH 01/16] docs: adds the removed types from IOpenAny Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 7860a2434..6c462f2ad 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -144,6 +144,28 @@ In v2, the equivalent code would be, ``` +> Note: as part of this change, the following types have been removed from the library: +> +> - AnyType +> - IOpenApiAny +> - OpenApiAnyCloneHelper +> - OpenApiArray +> - OpenApiBinary +> - OpenApiBoolean +> - OpenApiByte +> - OpenApiDate +> - OpenApiDateTime +> - OpenApiDouble +> - OpenApiFloat +> - OpenApiInteger +> - OpenApiLong +> - OpenApiNull +> - OpenApiObject +> - OpenApiPassword +> - OpenApiPrimitive +> - OpenApiString +> - PrimitiveType + ### Updates to OpenApiSchema The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema. In 3.0 and earlier, OpenAPI used a "subset, superset" of JSON Schema draft-4. This caused many problems for developers trying to use JSON Schema validation libraries with the JSON Schema in their OpenAPI descriptions. In OpenAPI 3.1, the 2020-12 draft version of JSON Schema was adopted and a new JSON Schema vocabulary was adopted to support OpenAPI specific keywords. All attempts to constrain what JSON Schema keywords could be used in OpenAPI were removed. From deea642a5c9a1dd96b88243cdc353f3e3fb66f57 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 12:51:52 -0400 Subject: [PATCH 02/16] docs: adds missing documentation around new exceptions Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 6c462f2ad..cb35ac99c 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -73,6 +73,13 @@ As the YAML format is only supported when including the `Microsoft.OpenApi.YamlR When the loading methods are used without a format parameter, we will attempt to parse the document using the default JSON reader. If that fails and the YAML reader is registered, then we will attempt to read as YAML. The goal is always to provide the fastest path with JSON but still maintain the convenience of not having to care whether a URL points to YAML or JSON if you need that flexibility. +### Additional exceptions + +While parsing an OpenAPI description, the library will now throw the following new exceptions: + +- `OpenApiReaderException` when the reader for the format cannot be found, the document cannot be parsed because it does not follow the format conventions, etc... +- `OpenApiUnsupportedSpecVersionException` when the document's version is not implemented by this version of the library and therefore cannot be parsed. + ### Removing the OpenAPI Any classes In the OpenAPI specification, there are a few properties that are defined as type `any`. This includes: From 7f3be25e20354fdf53fa5c35273d2d60c27993d4 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 12:57:00 -0400 Subject: [PATCH 03/16] docs: adds information about async methods Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index cb35ac99c..34ca46cfc 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -23,6 +23,22 @@ In v1, instances of `$ref` were resolved in a second pass of the document to ens [How does this change the behaviour of external references?] +### Asynchronous API surface + +Any method which results in input/output access (memory, network, storage) is now Async and returns a `Task` to avoid any blocking calls an improve concurrency. + +For example: + +```csharp +var result = myOperation.SerializeAsJson(OpenApiSpecVersion.OpenApi2_0); +``` + +Is now: + +```csharp +var result = await myOperation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); +``` + ## Reduced Dependencies In OpenAPI v1, it was necessary to include the Microsoft.OpenApi.Readers library to be able to read OpenAPI descriptions in either YAML or JSON. In OpenAPI.NET v2, the core Microsoft.OpenAPI library can both read and write JSON. It is only necessary to use the newly renamed [Microsoft.OpenApi.YamlReader](https://www.nuget.org/packages/Microsoft.OpenApi.YamlReader/) library if you need YAML support. This allows teams who are only working in JSON to avoid the additional dependency and therefore eliminate all non-.NET library references. From 305f0269a70568e61af3b58b560bbcd4c5f30c5b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:00:06 -0400 Subject: [PATCH 04/16] docs: adds information regarding trimming support Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 34ca46cfc..e3f797f9d 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -39,6 +39,14 @@ Is now: var result = await myOperation.SerializeAsJsonAsync(OpenApiSpecVersion.OpenApi2_0); ``` +### Trimming support + +To better support applications deployed in high performance environments or on devices which have limited compute available, any usage of reflection has been removed from the code base. This also brings support for trimming to the library. Any method relying on reflection has been removed or re-written. + +> Note: as part of this change, the following types have been removed: +> +> - StringExtensions + ## Reduced Dependencies In OpenAPI v1, it was necessary to include the Microsoft.OpenApi.Readers library to be able to read OpenAPI descriptions in either YAML or JSON. In OpenAPI.NET v2, the core Microsoft.OpenAPI library can both read and write JSON. It is only necessary to use the newly renamed [Microsoft.OpenApi.YamlReader](https://www.nuget.org/packages/Microsoft.OpenApi.YamlReader/) library if you need YAML support. This allows teams who are only working in JSON to avoid the additional dependency and therefore eliminate all non-.NET library references. From 4906d21f65f10f09b73fff2cbad6534facfdde72 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:06:03 -0400 Subject: [PATCH 05/16] docs: adds information about the null collections Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index e3f797f9d..26c0f4e3a 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -47,6 +47,29 @@ To better support applications deployed in high performance environments or on d > > - StringExtensions +### Collections are not initialized + +To lower the memory footprint of the library, collections are now NOT initialized anymore when instantiating any of the models. + +Example + +```csharp +var mySchema = new OpenApiSchema(); + +// 1.6: works +// 2.X: if null reference types is enabled in the target application, +// this will lead to a warning or error at compile time. +// And fail at runtime with a null reference exception. +mySchema.AnyOf.Add(otherSchema); + +// one solution +mySchema.AnyOf ??= []; +mySchema.AnyOf.Add(otherSchema); + +// alternative +mySchema.AnyOf = [otherSchema]; +``` + ## Reduced Dependencies In OpenAPI v1, it was necessary to include the Microsoft.OpenApi.Readers library to be able to read OpenAPI descriptions in either YAML or JSON. In OpenAPI.NET v2, the core Microsoft.OpenAPI library can both read and write JSON. It is only necessary to use the newly renamed [Microsoft.OpenApi.YamlReader](https://www.nuget.org/packages/Microsoft.OpenApi.YamlReader/) library if you need YAML support. This allows teams who are only working in JSON to avoid the additional dependency and therefore eliminate all non-.NET library references. From d6a5fe419496b79c96b4e24d0fb58ff68c1a369b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:10:15 -0400 Subject: [PATCH 06/16] docs: revamps the null reference exception information Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 26c0f4e3a..a83378770 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -220,6 +220,23 @@ In v2, the equivalent code would be, > - OpenApiString > - PrimitiveType +### Enable Null Reference Type Support + +Version 2.0 preview 13 introduces support for null reference types, which improves type safety and reduces the likelihood of null reference exceptions. + +**Example:** + +```csharp +var document = new OpenApiDocument +{ + Components = null +}; + +// 1.X: no compilation error or warning, but fails with a null reference exception at runtime +// 2.X: compilation error or warning depending on the project configuration +var componentA = document.Components["A"]; +``` + ### Updates to OpenApiSchema The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema. In 3.0 and earlier, OpenAPI used a "subset, superset" of JSON Schema draft-4. This caused many problems for developers trying to use JSON Schema validation libraries with the JSON Schema in their OpenAPI descriptions. In OpenAPI 3.1, the 2020-12 draft version of JSON Schema was adopted and a new JSON Schema vocabulary was adopted to support OpenAPI specific keywords. All attempts to constrain what JSON Schema keywords could be used in OpenAPI were removed. @@ -380,30 +397,6 @@ OpenApiOperation operation = new OpenApiOperation }; ``` -#### 2. Enable Null Reference Type Support - -Version 2.0 preview 13 introduces support for null reference types, which improves type safety and reduces the likelihood of null reference exceptions. - -**Example:** - -```csharp -// Before (1.6) -OpenApiDocument document = new OpenApiDocument -{ - Components = new OpenApiComponents() -}; - -// After (2.0) -OpenApiDocument document = new OpenApiDocument -{ - Components = new OpenApiComponents() - { - Schemas = new Dictionary() - } -}; - -``` - #### 3. References as Components References can now be used as components, allowing for more modular and reusable OpenAPI documents. From 14c04d2e54bb7967fc6c72e60ae62d8599212e0e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:13:20 -0400 Subject: [PATCH 07/16] docs: adds information regarding collections types Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index a83378770..0f3e2e62a 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -237,6 +237,19 @@ var document = new OpenApiDocument var componentA = document.Components["A"]; ``` +### Collections are implementations + +Any collection used by the model now documents using the implementation type instead of the interface. This facilitates the usage of new language features such as collections initialization. + +```csharp +var schema = new OpenApiSchema(); + +// 1.X: does not compile due to the lack of implementation type +// 2.X: compiles successfully +schema.AnyOf = []; +// now a List instead of IList +``` + ### Updates to OpenApiSchema The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema. In 3.0 and earlier, OpenAPI used a "subset, superset" of JSON Schema draft-4. This caused many problems for developers trying to use JSON Schema validation libraries with the JSON Schema in their OpenAPI descriptions. In OpenAPI 3.1, the 2020-12 draft version of JSON Schema was adopted and a new JSON Schema vocabulary was adopted to support OpenAPI specific keywords. All attempts to constrain what JSON Schema keywords could be used in OpenAPI were removed. From e0e0448dac1286e23764cd82a1218733625337a0 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:19:12 -0400 Subject: [PATCH 08/16] docs: adds change about annotations Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 0f3e2e62a..48ad76947 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -250,6 +250,19 @@ schema.AnyOf = []; // now a List instead of IList ``` +### Ephemeral object properties are now in Metadata + +In version 1.X applications could add ephemeral properties to some of the models from the libraries. These properties would be carried along in an "Annotations" property, but not serialized. This is especially helpful when building integrations that build document in multiple phases and need additional context to complete the work. The property is now named metadata to avoid any confusion with other terms. The parent interface has also been renamed from `IOpenApiAnnotatable` to `IMetadataContainer`. + +```csharp +var schema = new OpenApiSchema(); + +// 1.X +var info = schema.Annotations["foo"]; +// 2.X +var info = schema.Metadata["foo"]; +``` + ### Updates to OpenApiSchema The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema. In 3.0 and earlier, OpenAPI used a "subset, superset" of JSON Schema draft-4. This caused many problems for developers trying to use JSON Schema validation libraries with the JSON Schema in their OpenAPI descriptions. In OpenAPI 3.1, the 2020-12 draft version of JSON Schema was adopted and a new JSON Schema vocabulary was adopted to support OpenAPI specific keywords. All attempts to constrain what JSON Schema keywords could be used in OpenAPI were removed. From 2f7cd057554f032315ee3894ff35586158abc4c3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:26:31 -0400 Subject: [PATCH 09/16] docs: add information about read result deconstruction Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 48ad76947..e2f6e0e57 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -85,18 +85,24 @@ var result = OpenApiDocument.LoadAsync(openApiString, settings: settings); ## API Enhancements +### Loading the document + The v1 library attempted to mimic the pattern of `XmlTextReader` and `JsonTextReader` for the purpose of loading OpenAPI documents from strings, streams and text readers. ```csharp - var reader = new OpenApiStringReader(); - var openApiDoc = reader.Read(stringOpenApiDoc, out var diagnostic); +var reader = new OpenApiStringReader(); +var openApiDoc = reader.Read(stringOpenApiDoc, out var diagnostic); ``` -The same pattern can be used for `OpenApiStreamReader` and `OpenApiTextReader`. When we introduced the `ReadAsync` methods we eliminated the use of the `out` parameter. +The same pattern can be used for `OpenApiStreamReader` and `OpenApiTextReader`. When we introduced the `ReadAsync` methods we eliminated the use of the `out` parameter. To improve code readability, we've added deconstruction support to `ReadResult`. The properties also have been renamed to avoid confusion with their types. ```csharp - var reader = new OpenApiStreamReader(); - var (document, diagnostics) = await reader.ReadAsync(streamOpenApiDoc); +var reader = new OpenApiStreamReader(); +var (document, diagnostics) = await reader.ReadAsync(streamOpenApiDoc); +// or +var result = await reader.ReadAsync(streamOpenApiDoc); +var document = result.Document; +var diagnostics = result.Diagnostics; ``` A `ReadResult` object acts as a tuple of `OpenApiDocument` and `OpenApiDiagnostic`. From 6c1a630c8e4870e7adf987ac874555f329b8718d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:39:48 -0400 Subject: [PATCH 10/16] docs: adds follow up todos Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index e2f6e0e57..6ff4a4395 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -489,3 +489,16 @@ OpenApiSchemaReference schemaRef = new OpenApiSchemaReference("MySchema") If you have any feedback please file a GitHub issue [here](https://github.com/microsoft/OpenAPI.NET/issues) The team is looking forward to hear your experience trying the new version and we hope you have fun busting out your OpenAPI 3.1 descriptions. + +## Todos + +- Models now have matching interfaces + reference type + type assertion pattern + reference fields removed from the base model + Target + RecursiveTarget + removed OpenApiReferenceResolver. +- Workspace + component resolution. +- Visitor and Validator method now pass the interface model. +- Removed all the IEffective/GetEffective infrastructure. +- OpenApiSchema.Type is now a flag enum + bitwise operations. +- JsonSchemaDialect + BaseUri in document. +- Copy constructors are gone, use shallow copy method. +- Multiple methods that should have been internal have been changed from public to private link OpenApiLink.SerializeAsV3WithoutReference. +- duplicated _style property on parameter was removed. +- ValidationRuleSet now accepts a key? \ No newline at end of file From b2bd4cd7ab27aafe65dfce96b76c3878aad29222 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:42:34 -0400 Subject: [PATCH 11/16] chore: fixes indentation in code snippets Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 185 +++++++++++++++++++--------------------- 1 file changed, 88 insertions(+), 97 deletions(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 6ff4a4395..767209f22 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -149,58 +149,58 @@ In v2 we are removing this abstraction and relying on the `JsonNode` model to re Due to `JsonNode` implicit operators, this makes initialization sometimes easier, instead of: ```csharp - new OpenApiParameter - { - In = null, - Name = "username", - Description = "username to fetch", - Example = new OpenApiFloat(5), - }; +new OpenApiParameter +{ + In = null, + Name = "username", + Description = "username to fetch", + Example = new OpenApiFloat(5), +}; ``` the assignment becomes simply, ```csharp - Example = 0.5f, + Example = 0.5f, ``` For a more complex example, where the developer wants to create an extension that is an object they would do this in v1: ```csharp - var openApiObject = new OpenApiObject - { - {"stringProp", new OpenApiString("stringValue1")}, - {"objProp", new OpenApiObject()}, - { - "arrayProp", - new OpenApiArray - { - new OpenApiBoolean(false) - } - } - }; - var parameter = new OpenApiParameter(); - parameter.Extensions.Add("x-foo", new OpenApiAny(openApiObject)); +var openApiObject = new OpenApiObject +{ + {"stringProp", new OpenApiString("stringValue1")}, + {"objProp", new OpenApiObject()}, + { + "arrayProp", + new OpenApiArray + { + new OpenApiBoolean(false) + } + } +}; +var parameter = new OpenApiParameter(); +parameter.Extensions.Add("x-foo", new OpenApiAny(openApiObject)); ``` In v2, the equivalent code would be, ```csharp - var openApiObject = new JsonObject - { - {"stringProp", "stringValue1"}, - {"objProp", new JsonObject()}, - { - "arrayProp", - new JsonArray - { - false - } - } - }; - var parameter = new OpenApiParameter(); - parameter.Extensions.Add("x-foo", new OpenApiAny(openApiObject)); +var openApiObject = new JsonObject +{ + {"stringProp", "stringValue1"}, + {"objProp", new JsonObject()}, + { + "arrayProp", + new JsonArray + { + false + } + } +}; +var parameter = new OpenApiParameter(); +parameter.Extensions.Add("x-foo", new OpenApiAny(openApiObject)); ``` @@ -298,25 +298,24 @@ The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema #### Changes to existing keywords ```csharp - - public string? ExclusiveMaximum { get; set; } // type changed to reflect the new version of JSON schema - public string? ExclusiveMinimum { get; set; } // type changed to reflect the new version of JSON schema - public JsonSchemaType? Type { get; set; } // Was string, now flagged enum - public string? Maximum { get; set; } // type changed to overcome double vs decimal issues - public string? Minimum { get; set; } // type changed to overcome double vs decimal issues - - public JsonNode Default { get; set; } // Type matching no longer enforced. Was IOpenApiAny - public bool ReadOnly { get; set; } // No longer has defined semantics in OpenAPI 3.1 - public bool WriteOnly { get; set; } // No longer has defined semantics in OpenAPI 3.1 - - public JsonNode Example { get; set; } // No longer IOpenApiAny - public IList Examples { get; set; } - public IList Enum { get; set; } - public OpenApiExternalDocs ExternalDocs { get; set; } // OpenApi Vocab - public bool Deprecated { get; set; } // OpenApi Vocab - public OpenApiXml Xml { get; set; } // OpenApi Vocab - - public IDictionary Metadata { get; set; } // Custom property bag to be used by the application, used to be named annotations +public string? ExclusiveMaximum { get; set; } // type changed to reflect the new version of JSON schema +public string? ExclusiveMinimum { get; set; } // type changed to reflect the new version of JSON schema +public JsonSchemaType? Type { get; set; } // Was string, now flagged enum +public string? Maximum { get; set; } // type changed to overcome double vs decimal issues +public string? Minimum { get; set; } // type changed to overcome double vs decimal issues + +public JsonNode Default { get; set; } // Type matching no longer enforced. Was IOpenApiAny +public bool ReadOnly { get; set; } // No longer has defined semantics in OpenAPI 3.1 +public bool WriteOnly { get; set; } // No longer has defined semantics in OpenAPI 3.1 + +public JsonNode Example { get; set; } // No longer IOpenApiAny +public IList Examples { get; set; } +public IList Enum { get; set; } +public OpenApiExternalDocs ExternalDocs { get; set; } // OpenApi Vocab +public bool Deprecated { get; set; } // OpenApi Vocab +public OpenApiXml Xml { get; set; } // OpenApi Vocab + +public IDictionary Metadata { get; set; } // Custom property bag to be used by the application, used to be named annotations ``` #### OpenApiSchema methods @@ -324,13 +323,13 @@ The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema Other than the addition of `SerializeAsV31`, the methods have not changed. ```csharp -public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable +public class OpenApiSchema : IOpenApiMetadataContainer, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable { - public OpenApiSchema() { } - public OpenApiSchema(OpenApiSchema schema) { } - public void SerializeAsV31(IOpenApiWriter writer) { } - public void SerializeAsV3(IOpenApiWriter writer) { } - public void SerializeAsV2(IOpenApiWriter writer) { } + public OpenApiSchema() { } + public OpenApiSchema(OpenApiSchema schema) { } + public void SerializeAsV31(IOpenApiWriter writer) { } + public void SerializeAsV3(IOpenApiWriter writer) { } + public void SerializeAsV2(IOpenApiWriter writer) { } } ``` @@ -343,60 +342,52 @@ There are a number of new features in OpenAPI v3.1 that are now supported in Ope ```csharp -public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenApiAnnotatable { - /// - /// The incoming webhooks that MAY be received as part of this API and that the API consumer MAY choose to implement. - /// A map of requests initiated other than by an API call, for example by an out of band registration. - /// The key name is a unique string to refer to each webhook, while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider and the expected responses - /// - public IDictionary? Webhooks { get; set; } = new Dictionary(); +public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenApiMetadataContainer +{ + public IDictionary? Webhooks { get; set; } = new Dictionary(); } ``` ### Summary in info object ```csharp - +public class OpenApiInfo : IOpenApiSerializable, IOpenApiExtensible +{ /// - /// Open API Info Object, it provides the metadata about the Open API. + /// A short summary of the API. /// - public class OpenApiInfo : IOpenApiSerializable, IOpenApiExtensible - { - /// - /// A short summary of the API. - /// - public string Summary { get; set; } - } + public string Summary { get; set; } +} ``` ### License SPDX identifiers ```csharp +/// +/// License Object. +/// +public class OpenApiLicense : IOpenApiSerializable, IOpenApiExtensible +{ /// - /// License Object. + /// An SPDX license expression for the API. The identifier field is mutually exclusive of the Url property. /// - public class OpenApiLicense : IOpenApiSerializable, IOpenApiExtensible - { - /// - /// An SPDX license expression for the API. The identifier field is mutually exclusive of the Url property. - /// - public string Identifier { get; set; } - } + public string Identifier { get; set; } +} ``` ### Reusable path items ```csharp +/// +/// Components Object. +/// +public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible +{ /// - /// Components Object. + /// An object to hold reusable Object. /// - public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible - { - /// - /// An object to hold reusable Object. - /// - public IDictionary? PathItems { get; set; } = new Dictionary(); - } + public IDictionary? PathItems { get; set; } = new Dictionary(); +} ``` #### Summary and Description alongside $ref @@ -404,10 +395,10 @@ public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenA Through the use of proxy objects in order to represent references, it is now possible to set the Summary and Description property on an object that is a reference. This was previously not possible. ```csharp - var parameter = new OpenApiParameterReference("id", hostdocument) - { - Description = "Customer Id" - }; +var parameter = new OpenApiParameterReference("id", hostdocument) +{ + Description = "Customer Id" +}; ``` ### Use HTTP Method Object Instead of Enum From 21f668714015dc1ecc93cde92989029650cd7b35 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 13:43:57 -0400 Subject: [PATCH 12/16] chore: additional indenting Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 767209f22..6c57054f5 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -276,22 +276,22 @@ The OpenAPI 3.1 specification changes significantly how it leverages JSON Schema #### New keywords introduced in 2020-12 ```csharp - /// $schema, a JSON Schema dialect identifier. Value must be a URI - public string Schema { get; set; } - /// $id - Identifies a schema resource with its canonical URI. - public string Id { get; set; } - /// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. - public string Comment { get; set; } - /// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. - public IDictionary Vocabulary { get; set; } - /// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance - public string DynamicRef { get; set; } - /// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. - public string DynamicAnchor { get; set; } - /// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. - public IDictionary Definitions { get; set; } - public IDictionary PatternProperties { get; set; } = new Dictionary(); - public bool UnevaluatedProperties { get; set;} +/// $schema, a JSON Schema dialect identifier. Value must be a URI +public string Schema { get; set; } +/// $id - Identifies a schema resource with its canonical URI. +public string Id { get; set; } +/// $comment - reserves a location for comments from schema authors to readers or maintainers of the schema. +public string Comment { get; set; } +/// $vocabulary- used in meta-schemas to identify the vocabularies available for use in schemas described by that meta-schema. +public IDictionary Vocabulary { get; set; } +/// $dynamicRef - an applicator that allows for deferring the full resolution until runtime, at which point it is resolved each time it is encountered while evaluating an instance +public string DynamicRef { get; set; } +/// $dynamicAnchor - used to create plain name fragments that are not tied to any particular structural location for referencing purposes, which are taken into consideration for dynamic referencing. +public string DynamicAnchor { get; set; } +/// $defs - reserves a location for schema authors to inline re-usable JSON Schemas into a more general schema. +public IDictionary Definitions { get; set; } +public IDictionary PatternProperties { get; set; } = new Dictionary(); +public bool UnevaluatedProperties { get; set;} ``` From 55ef6dd5c99ad93883942ab73ab4ce96c105a9f5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 14:01:46 -0400 Subject: [PATCH 13/16] docs: adds test results Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 6c57054f5..d3906921d 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -23,6 +23,29 @@ In v1, instances of `$ref` were resolved in a second pass of the document to ens [How does this change the behaviour of external references?] +### Results + +The following benchmark results outline an overall 50% reduction in processing time for the document parsing as well as 35% reduction in memory allocation when parsing JSON. +For YAML, the results between the different versions of the library are similar (some of the optimizations being compensated by the additional features). + +#### 1.X + +| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------- |---------------:|-------------:|-------------:|-----------:|-----------:|----------:|-------------:| +| PetStoreYaml | 448.7 μs | 326.6 μs | 17.90 μs | 58.5938 | 11.7188 | - | 381.79 KB | +| PetStoreJson | 484.8 μs | 156.9 μs | 8.60 μs | 62.5000 | 15.6250 | - | 389.28 KB | +| GHESYaml | 1,008,349.6 μs | 565,392.0 μs | 30,991.04 μs | 66000.0000 | 23000.0000 | 4000.0000 | 382785 KB | +| GHESJson | 1,039,447.0 μs | 267,501.0 μs | 14,662.63 μs | 67000.0000 | 23000.0000 | 4000.0000 | 389970.77 KB | + +#### 2.X + +| Method | Mean | Error | StdDev | Gen0 | Gen1 | Gen2 | Allocated | +|------------- |-------------:|--------------:|-------------:|-----------:|-----------:|----------:|-------------:| +| PetStoreYaml | 450.5 μs | 59.26 μs | 3.25 μs | 58.5938 | 11.7188 | - | 377.15 KB | +| PetStoreJson | 172.8 μs | 123.46 μs | 6.77 μs | 39.0625 | 7.8125 | - | 239.29 KB | +| GHESYaml | 943,452.7 μs | 137,685.49 μs | 7,547.01 μs | 66000.0000 | 21000.0000 | 3000.0000 | 389463.91 KB | +| GHESJson | 468,401.8 μs | 300,711.80 μs | 16,483.03 μs | 41000.0000 | 15000.0000 | 3000.0000 | 250934.62 KB | + ### Asynchronous API surface Any method which results in input/output access (memory, network, storage) is now Async and returns a `Task` to avoid any blocking calls an improve concurrency. From 83778c976b142c8912d90da092856e8ce00df2a2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 14:06:41 -0400 Subject: [PATCH 14/16] docs: fixes heading issues Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index d3906921d..4ed916dae 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -413,7 +413,7 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible } ``` -#### Summary and Description alongside $ref +### Summary and Description alongside $ref Through the use of proxy objects in order to represent references, it is now possible to set the Summary and Description property on an object that is a reference. This was previously not possible. @@ -424,6 +424,13 @@ var parameter = new OpenApiParameterReference("id", hostdocument) }; ``` +Once serialized results in: + +```yaml +$ref: id +description: Customer Id +``` + ### Use HTTP Method Object Instead of Enum HTTP methods are now represented as objects instead of enums. This change enhances flexibility but requires updates to how HTTP methods are handled in your code. @@ -443,7 +450,7 @@ OpenApiOperation operation = new OpenApiOperation }; ``` -#### 3. References as Components +### References as Components References can now be used as components, allowing for more modular and reusable OpenAPI documents. @@ -465,9 +472,9 @@ OpenApiComponents components = new OpenApiComponents { Schemas = new Dictionary { - ["MySchema"] = new OpenApiSchema + ["MySchema"] = new OpenApiSchemaReference("MyOtherSchema") { - Reference = new OpenApiSchemaReference("MySchema") + Description = "Other reusable schema from initial schema" } } }; From 2272b87a21e9dc2d5b9568c1ba0a2d1af71eb065 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 11 Apr 2025 14:10:17 -0400 Subject: [PATCH 15/16] chore: adds a todo to document Signed-off-by: Vincent Biret --- docs/upgrade-guide-2.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 4ed916dae..399daef44 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -522,4 +522,5 @@ The team is looking forward to hear your experience trying the new version and w - Copy constructors are gone, use shallow copy method. - Multiple methods that should have been internal have been changed from public to private link OpenApiLink.SerializeAsV3WithoutReference. - duplicated _style property on parameter was removed. +- discriminator now uses references. - ValidationRuleSet now accepts a key? \ No newline at end of file From b1fd77baac2ac33b341b1f66faf23daf47b0a99c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 14 Apr 2025 08:24:38 -0400 Subject: [PATCH 16/16] Update docs/upgrade-guide-2.md Co-authored-by: Maggie Kimani --- docs/upgrade-guide-2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/upgrade-guide-2.md b/docs/upgrade-guide-2.md index 399daef44..c1416b8fe 100644 --- a/docs/upgrade-guide-2.md +++ b/docs/upgrade-guide-2.md @@ -346,7 +346,7 @@ public IDictionary Metadata { get; set; } // Custom property ba Other than the addition of `SerializeAsV31`, the methods have not changed. ```csharp -public class OpenApiSchema : IOpenApiMetadataContainer, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable +public class OpenApiSchema : IMetadataContainer, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable { public OpenApiSchema() { } public OpenApiSchema(OpenApiSchema schema) { }