diff --git a/.gitignore b/.gitignore index c340dff..954c945 100644 --- a/.gitignore +++ b/.gitignore @@ -397,3 +397,4 @@ FodyWeavers.xsd # JetBrains Rider *.sln.iml +/Graeae.Models/OpenApi.Models.xml diff --git a/Graeae.Models.Tests/Files/payload-invalid1.json b/Graeae.Models.Tests/Files/payload-invalid1.json new file mode 100644 index 0000000..db5a68f --- /dev/null +++ b/Graeae.Models.Tests/Files/payload-invalid1.json @@ -0,0 +1,6 @@ +{ + "inner": { + "a": "test", + "b": true + } +} \ No newline at end of file diff --git a/Graeae.Models.Tests/Files/payload-invalid2.json b/Graeae.Models.Tests/Files/payload-invalid2.json new file mode 100644 index 0000000..003379b --- /dev/null +++ b/Graeae.Models.Tests/Files/payload-invalid2.json @@ -0,0 +1,6 @@ +{ + "inner": { + "a": "test" + }, + "b": true +} \ No newline at end of file diff --git a/Graeae.Models.Tests/Files/payload-invalid3.json b/Graeae.Models.Tests/Files/payload-invalid3.json new file mode 100644 index 0000000..74d1d7e --- /dev/null +++ b/Graeae.Models.Tests/Files/payload-invalid3.json @@ -0,0 +1,4 @@ +{ + "inner": { + } +} \ No newline at end of file diff --git a/Graeae.Models.Tests/Files/payload-invalid4.json b/Graeae.Models.Tests/Files/payload-invalid4.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/Graeae.Models.Tests/Files/payload-invalid4.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/Graeae.Models.Tests/Files/payload-valid.json b/Graeae.Models.Tests/Files/payload-valid.json new file mode 100644 index 0000000..2a32683 --- /dev/null +++ b/Graeae.Models.Tests/Files/payload-valid.json @@ -0,0 +1,5 @@ +{ + "inner": { + "a": "test" + } +} \ No newline at end of file diff --git a/Graeae.Models.Tests/Files/schema-components.json b/Graeae.Models.Tests/Files/schema-components.json new file mode 100644 index 0000000..7d330e8 --- /dev/null +++ b/Graeae.Models.Tests/Files/schema-components.json @@ -0,0 +1,35 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Doc for payload validation", + "version": "1.0.0" + }, + "components": { + "schemas": { + "outer": { + "type": "object", + "properties": { + "inner": { + "$ref": "#/components/schemas/inner" + } + }, + "required": [ + "inner" + ], + "additionalProperties": false + }, + "inner": { + "type": "object", + "properties": { + "a": { + "type": "string" + } + }, + "required": [ + "a" + ], + "additionalProperties": false + } + } + } +} diff --git a/Graeae.Models.Tests/PayloadValidationTests.cs b/Graeae.Models.Tests/PayloadValidationTests.cs new file mode 100644 index 0000000..92dff8d --- /dev/null +++ b/Graeae.Models.Tests/PayloadValidationTests.cs @@ -0,0 +1,60 @@ +using System.Text.Json; +using Graeae.Models.SchemaDraft4; +using Json.Pointer; +using Json.Schema; + +namespace Graeae.Models.Tests; + +public class PayloadValidationTests +{ + + [TestCase("payload-valid.json")] + public async Task ReferencesValid(string fileName) + { + var schemaFileName = GetFile("schema-components.json"); + var fileText = File.ReadAllText(schemaFileName); + var openApiDoc = JsonSerializer.Deserialize(fileText, TestSerializerContext.Default.OpenApiDocument); + + var options = new EvaluationOptions + { + EvaluateAs = Draft4Support.Draft4Version, + }; + await openApiDoc!.Initialize(options.SchemaRegistry); + + var componentRef = JsonPointer.Parse("#/components/schemas/outer"); + var fullFileName = GetFile(fileName); + var payloadJson = File.ReadAllText(fullFileName); + var document = JsonDocument.Parse(payloadJson); + + var results = openApiDoc.EvaluatePayload(document, componentRef, options); + Assert.True(results!.IsValid); + } + + + [TestCase("payload-invalid1.json")] + [TestCase("payload-invalid2.json")] + [TestCase("payload-invalid3.json")] + [TestCase("payload-invalid4.json")] + public async Task ReferencesInvalid(string fileName) + { + var schemaFileName = GetFile("schema-components.json"); + + var fileText = File.ReadAllText(schemaFileName); + var openApiDoc = JsonSerializer.Deserialize(fileText, TestSerializerContext.Default.OpenApiDocument); + + var options = new EvaluationOptions + { + EvaluateAs = Draft4Support.Draft4Version, + }; + await openApiDoc!.Initialize(options.SchemaRegistry); + + var componentRef = JsonPointer.Parse("#/components/schemas/outer"); + + var fullFileName = GetFile(fileName); + var payloadJson = File.ReadAllText(fullFileName); + var document = JsonDocument.Parse(payloadJson); + + var results = openApiDoc.EvaluatePayload(document, componentRef, options); + Assert.False(results!.IsValid); + } +} \ No newline at end of file diff --git a/Graeae.Models.Tests/ValidationTests.cs b/Graeae.Models.Tests/ValidationTests.cs index 649f4d1..5c01345 100644 --- a/Graeae.Models.Tests/ValidationTests.cs +++ b/Graeae.Models.Tests/ValidationTests.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using System.Text.Json.Nodes; using Json.Schema; using Yaml2JsonNode; @@ -53,4 +54,4 @@ public void ValidateOpenApiDoc_3_1(string fileName) Assert.IsTrue(results.IsValid); } -} +} \ No newline at end of file diff --git a/Graeae.Models/Graeae.Models.csproj b/Graeae.Models/Graeae.Models.csproj index f905d15..9e038d8 100644 --- a/Graeae.Models/Graeae.Models.csproj +++ b/Graeae.Models/Graeae.Models.csproj @@ -16,11 +16,11 @@ openapi.png https://github.com/gregsdennis/Graeae openapi json schema models - Release notes can be found at https://github.com/gregsdennis/Graeae + Edit Release notes in file RELEASE_NOTES.md in the repo root. true Graeae.Models.xml - 0.3.0 - 0.3.0.0 + 0.3.1 + 0.3.1.0 0.3.0.0 true snupkg @@ -53,4 +53,12 @@ + + + + + + @(ReleaseNoteLines, '%0a') + + diff --git a/Graeae.Models/Graeae.Models.xml b/Graeae.Models/Graeae.Models.xml index 5f37c52..cd4c82d 100644 --- a/Graeae.Models/Graeae.Models.xml +++ b/Graeae.Models/Graeae.Models.xml @@ -871,6 +871,41 @@ The expected location The object, if an object of that type exists at that location; otherwise null. + + + Provides extensions on various OpenAPI types. + + + + + Validates a payload against the schema at the indicated location. + + The OpenAPI document. + The payload to validate. + The location within the document where the schema can be found. + (optional) The evaluation options. This should be the same options object used to initialize the OpenAPI document. + The evaluation options if the schema was found; otherwise null. + + + + Validates a payload against the schema at the indicated location. + + The OpenAPI document. + The payload to validate. + The location within the document where the schema can be found. + (optional) The evaluation options. This should be the same options object used to initialize the OpenAPI document. + The evaluation options if the schema was found; otherwise null. + + + + Validates a payload against the schema at the indicated location. + + The OpenAPI document. + The payload to validate. + The location within the document where the schema can be found. + (optional) The evaluation options. This should be the same options object used to initialize the OpenAPI document. + The evaluation options if the schema was found; otherwise null. + Models the info object. diff --git a/Graeae.Models/OpenApi.Models.xml b/Graeae.Models/OpenApi.Models.xml deleted file mode 100644 index 7bfca5f..0000000 --- a/Graeae.Models/OpenApi.Models.xml +++ /dev/null @@ -1,2147 +0,0 @@ - - - - OpenApi.Models - - - - - Models a callback. - - - - - Gets or set extension data. - - - - - Models a `$ref` to a callback. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Models a callback key expression. - - - - - Gets the parameters that exist in the key expression. - - - - - (not yet implemented) Resolves the callback expression. - - Throws not implemented. - It's not implemented. - - In order to implement this, an HttpRequest or HttpResponse is required, which - means adding a reference to ASP.net. As a result, it may make more sense for - resolution functionality to exist in a secondary package. - - - - Indicates whether the current object is equal to another object of the same type. - An object to compare with this object. - - if the current object is equal to the parameter; otherwise, . - - - Returns a string that represents the current object. - A string that represents the current object. - - - - Implicitly converts a string to a via parsing. - - A - - - - Models the `components` collection. - - - - - Gets or sets the schema components. - - - - - Gets or sets the response components. - - - - - Gets or sets the parameter components. - - - - - Gets or sets the example components. - - - - - Gets or sets the request body components. - - - - - Gets or sets the header components. - - - - - Gets or sets the security scheme components. - - - - - Gets or sets the link components. - - - - - Gets or sets the callback components. - - - - - Gets or sets the path item components. - - - - - Gets or set extension data. - - - - - Models the contact information. - - - - - Gets or sets the contact name. - - - - - Gets or sets the contact URL. - - - - - Gets or sets the contact email. - - - - - Gets or set extension data. - - - - - Models an encoding object. - - - - - Gets or sets the encoding content type. - - - - - Gets or sets headers. - - - - - Gets or sets the encoding parameter style. - - - - - Gets or sets whether this will be exploded into multiple parameters. - - - - - Gets or sets whether the parameter value SHOULD allow reserved characters. - - - - - Gets or set extension data. - - - - - Models an example. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets or sets the example value. - - - - - Gets or sets a URI that points to the literal example. - - - - - Gets or set extension data. - - - - - Models a `$ref` to an example. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Supports extension data for all types. - - - - - Models external documentation. - - - - - Gets or sets the description. - - - - - Gets the URL for the target documentation. - - - - - Gets or set extension data. - - - - - Creates a new - - The URL for the target documentation. - - - - Creates a new - - The URL for the target documentation. - - - - Provides extended JSON Schema formats. - - - - - Validates that a number is a valid 32-bit integer. - - - - - Validates that a number is a valid 64-bit integer. - - - - - Validates that a number is a valid single-precision floating point value. - - - - - Validates that a number is a valid double-precision floating point value. - - - - - Validates that a string is a password. - - - - - Models a header. - - - - - Gets or sets the description. - - - - - Gets or sets whether the header is required. - - - - - Gets or sets whether the header is deprecated. - - - - - Gets or sets whether the header can be present with an empty value. - - - - - Gets or sets how the header value will be serialized. - - - - - Gets or sets whether this will be exploded into multiple parameters. - - - - - Gets or sets whether the parameter value should allow reserved characters. - - - - - Gets or sets a schema for the content. - - - - - Gets or sets an example. - - - - - Gets or sets a collection of examples. - - - - - Gets or sets a collection of content. - - - - - Gets or set extension data. - - - - - Models a `$ref` to a header. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Indicates that the item is a reference to another object rather than being the object itself. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Resolves the reference. - - The document root. - A task. - - - - Models the license information. - - - - - Gets license name used for the API. - - - - - Gets or sets an SPDX license expression for the API. - - - - - Gets or sets URL to the license used for the API. - - - - - Gets or set extension data. - - - - - Creates a new - - The license name used for the API. - - - - Models a link object. - - - - - Gets or sets a relative or absolute URI reference to an OAS operation. - - - - - Gets or sets the name of the operation. - - - - - Gets or sets the parameter collection. - - - - - Gets or sets the request body for the target operation. - - - - - Gets or sets the description. - - - - - Gets or sets the server for the target operation. - - - - - Gets or set extension data. - - - - - Models a `$ref` to a link. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Models a media type object. - - - - - Gets or sets a schema for the meta type. - - - - - Gets or sets an example. - - - - - Gets or sets a collection of examples. - - - - - Gets or sets a collection of encodings. - - - - - Gets or set extension data. - - - - - Models an OAuth flow. - - - - - Gets the authorization URL. - - - - - Gets the token URL. - - - - - Gets or sets the refresh token URL. - - - - - Gets the scopes. - - - - - Gets or set extension data. - - - - - Creates a new - - The authorization URL - The token URL - The scopes - - - - Models the OAuth flow collection. - - - - - Gets or sets the implicit flow. - - - - - Gets or sets the password flow. - - - - - Gets or sets the client-credentials flow. - - - - - Gets or sets the authorization-code flow. - - - - - Gets or set extension data. - - - - - Models the OpenAPI document. - - - - - Gets the OpenAPI document version. - - - - - Gets the API information. - - - - - Gets or sets the default JSON Schema dialect. - - - - - Gets or sets the server collection. - - - - - Gets or sets the paths collection. - - - - - Gets or sets the webhooks collection. - - - - - Gets or sets the components collection. - - - - - Gets or sets the security requirements collection. - - - - - Gets or sets the tags. - - - - - Gets or sets external documentation. - - - - - Gets or set extension data. - - - - - Creates a new - - The OpenAPI version - The API information - - - - Initializes the document model. - - - Thrown if a reference cannot be resolved. - - - - Finds and retrieves an object within the document at a specified location. - - The type of object - The expected location - The object, if an object of that type exists at that location; otherwise null. - - - - Models the info object. - - - - - Gets the title. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets or sets the link to the terms of service. - - - - - Gets or sets the contact information. - - - - - Gets or sets the license information. - - - - - Gets or sets the API version. - - - - - Gets or set extension data. - - - - - Creates a new - - The title - The API version - - - - Models an operation. - - - - - Gets or sets the tags. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets or sets external documentation. - - - - - Gets or sets the operation ID. - - - - - Gets or sets the parameters. - - - - - Gets or sets the request body. - - - - - Gets or sets the response collection. - - - - - Gets or sets the callbacks collection. - - - - - Gets or sets whether the operation is deprecated. - - - - - Gets or sets the security requirements. - - - - - Gets or sets the server collection. - - - - - Gets or set extension data. - - - - - Models a parameter. - - - - - Gets the name. - - - - - Gets the parameter location. - - - - - Gets or sets the description. - - - - - Gets or sets whether the parameter is required. - - - - - Gets or sets whether the parameter is deprecated. - - - - - Gets or sets whether the parameter is allowed to be present with an empty value. - - - - - Gets or sets how the parameter value will be serialized. - - - - - Gets or sets whether this will be exploded into multiple parameters. - - - - - Gets or sets whether the parameter value should allow reserved characters. - - - - - Gets or sets a schema for the content. - - - - - Gets or sets an example. - - - - - Gets or sets a collection of examples. - - - - - Gets or sets a collection of content. - - - - - Gets or set extension data. - - - - - Creates a new - - The name - The parameter location - - - - Models a `$ref` to a parameter. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Defines the different parameter locations. - - - - - Indicates the location is unknown. - - - - - Indicates the parameter is in the query string. - - - - - Indicates the parameter is in a header. - - - - - Indicates the parameter is in the path. - - - - - Indicates the parameter is in a cookie. - - - - - Defines the different parameter styles. - - - - - Indicates the parameter type is unknown. - - - - - Path-style parameters defined by RFC6570 - - - - - Label style parameters defined by RFC6570 - - - - - Form style parameters defined by RFC6570 - - - - - Simple style parameters defined by RFC6570 - - - - - Space separated array or object values - - - - - Pipe separated array or object values - - - - - Provides a simple way of rendering nested objects using form parameters - - - - - Models a path collection. - - - - - Gets or set extension data. - - - - - Models an individual path. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets or sets the GET operation. - - - - - Gets or sets the PUT operation. - - - - - Gets or sets the POST operation. - - - - - Gets or sets the DELETE operation. - - - - - Gets or sets the OPTIONS operation. - - - - - Gets or sets the HEAD operation. - - - - - Gets or sets the PATCH operation. - - - - - Gets or sets the TRACE operation. - - - - - Gets or sets the collection of servers. - - - - - Gets or sets the collection of parameters. - - - - - Gets or set extension data. - - - - - Models a `$ref` to a path item. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Models a templated path URI. - - - - - Gets the segments of the path. - - - - - Parses a new path template from a string. - - The string source - A path template. - - - - Attempts to parse a new path template from a string. - - The string source - The path template if the parse succeeded, otherwise null - True if the parse succeeded, otherwise false. - - - Returns a string that represents the current object. - A string that represents the current object. - - - Indicates whether the current object is equal to another object of the same type. - An object to compare with this object. - - if the current object is equal to the parameter; otherwise, . - - - Indicates whether the current object is equal to another object of the same type. - An object to compare with this object. - - if the current object is equal to the parameter; otherwise, . - - - Determines whether the specified object is equal to the current object. - The object to compare with the current object. - - if the specified object is equal to the current object; otherwise, . - - - Serves as the default hash function. - A hash code for the current object. - - - - Implicitly converts a string to a path template via parsing. - - The string source. - - - - Allows customization of `$ref` resolutions. - - - - - Provides factory methods for creating references to objects in the components collection. - - - - - Creates a reference to a callback. - - The key that identifies the callback. - The reference. - - - - Creates a reference to a example. - - The key that identifies the example. - The reference. - - - - Creates a reference to a header. - - The key that identifies the header. - The reference. - - - - Creates a reference to a link. - - The key that identifies the link. - The reference. - - - - Creates a reference to a parameter. - - The key that identifies the parameter. - The reference. - - - - Creates a reference to a path item. - - The key that identifies the path item. - The reference. - - - - Creates a reference to a request body. - - The key that identifies the request body. - The reference. - - - - Creates a reference to a response. - - The key that identifies the response. - The reference. - - - - Creates a reference to a schema. - - The key that identifies the schema. - The reference. - - - - Creates a reference to a security scheme. - - The key that identifies the security scheme. - The reference. - - - - Gets or sets the `$ref` fetching function. - - - - - Defines a default basic fetching function that uses an - and supports YAML and JSON content. - - The resource URI - The JSON content as a `JsonNode` - - - - Thrown when a `$ref` cannot be resolved. - - - - - Creates a new - - The exception message. - - - - Models a request body. - - - - - Gets or sets the description. - - - - - Gets the content collection. - - - - - Gets or sets whether the request body is required. - - - - - Gets or set extension data. - - - - - Creates a new - - - - - - Models a `$ref` to a request body. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Models a response. - - - - - Gets the description. - - - - - Gets or sets the header collection. - - - - - Gets or sets the content collection. - - - - - Gets or sets the link collection. - - - - - Gets or set extension data. - - - - - Creates a new - - The description - - - - Models a `$ref` to a response. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Models a response collection. - - - - - Gets or sets the default response for the collection. - - - - - Gets or set extension data. - - - - - Models an OpenAPI runtime expression. - - - - - A `$url` runtime expression. - - - - - A `$method` runtime expression. - - - - - A `$statusCode` runtime expression. - - - - - Gets the expression type. - - - - - Gets the source type. - - - - - Gets the token. - - - - - Gets the name. - - - - - Gets the JSON Pointer. - - - - - Parses a runtime expression from a string. - - The string source - A runtime expression - Throw when the parse fails - - - Returns a string that represents the current object. - A string that represents the current object. - - - Indicates whether the current object is equal to another object of the same type. - An object to compare with this object. - - if the current object is equal to the parameter; otherwise, . - - - Indicates whether the current object is equal to another object of the same type. - An object to compare with this object. - - if the current object is equal to the parameter; otherwise, . - - - Determines whether the specified object is equal to the current object. - The object to compare with the current object. - - if the specified object is equal to the current object; otherwise, . - - - Serves as the default hash function. - A hash code for the current object. - - - - Defines the different runtime expression sources. - - - - - Indicates the expression source type is unknown. - - - - - Indicates the expression source is the header. - - - - - Indicates the expression source is the query string. - - - - - Indicates the expression source is the path. - - - - - Indicates the expression source is the body. - - - - - Defines the different types of runtime expressions. - - - - - Indicates the expression type is unknown. - - - - - Indicates a `$url` expression. - - - - - Indicates a `$method` expression. - - - - - Indicates a `$statusCode` expression. - - - - - Indicates a `$request` expression. - - - - - Indicates a `$response` expression. - - - - - Overrides the JSON Schema to support draft 4 boolean values. - - - - - The name of the keyword. - - - - - The boolean value, if it's a boolean. - - - - - The number value, if it's a number. - - - - - Creates a new . - - Whether the `minimum` value should be considered exclusive. - - - - Creates a new . - - The minimum value. - - - Builds a constraint object for a keyword. - The for the schema object that houses this keyword. - - The set of other s that have been processed prior to this one. - Will contain the constraints for keyword dependencies. - - The . - A constraint object. - - - - Overrides the JSON Schema to support draft 4 boolean values. - - - - - The name of the keyword. - - - - - The boolean value, if it's a boolean. - - - - - The number value, if it's a number. - - - - - Creates a new . - - Whether the `minimum` value should be considered exclusive. - - - - Creates a new . - - The minimum value. - - - Builds a constraint object for a keyword. - The for the schema object that houses this keyword. - - The set of other s that have been processed prior to this one. - Will contain the constraints for keyword dependencies. - - The . - A constraint object. - - - - Represents the JSON Schema draft 4 `id` keyword. - - - - - The name of the keyword. - - - - - The ID. - - - - - Creates a new . - - The ID. - - - Builds a constraint object for a keyword. - The for the schema object that houses this keyword. - - The set of other s that have been processed prior to this one. - Will contain the constraints for keyword dependencies. - - The . - A constraint object. - - - - Provides additional functionality for JSON Schema draft 4 support. - - - - - Defines a JSON Schema draft 4 spec version. - - - - - Defines the OpenAPI / JSON Schema draft 4 `file` type. - - - - - Defines the JSON Schema draft 4 meta-schema URI. - - - - - Defines the JSON Schema draft 4 meta-schema. - - - - - Enables support for OpenAPI v3.0 and JSON Schema draft 4. - - - - - Overrides the JSON Schema to support draft 4. - - - - - The name of the keyword. - - - - - The ID. - - - - - Creates a new . - - The instance type that is allowed. - - - Builds a constraint object for a keyword. - The for the schema object that houses this keyword. - - The set of other s that have been processed prior to this one. - Will contain the constraints for keyword dependencies. - - The . - A constraint object. - - - - Provides extension methods for explicitly building draft 4 schemas. - - - - - Adds the draft 4 `exclusiveMaximum` override. - - The builder - The value - The builder - - - - Adds the draft 4 `exclusiveMinimum` override. - - The builder - The value - The builder - - - - Adds the draft 4 `id` override. - - The builder - The id - The builder - - - - Adds the draft 4 `id` override. - - The builder - The id - The builder - - - - Adds the draft 4 `type` override. - - The builder - The type - The builder - - - - Adds the `nullable` keyword. - - The builder - The value - The builder - - - - Provides the OpenAPI `nullable` keyword. - - - - - The name of the keyword. - - - - - The ID. - - - - - Creates a new . - - Whether the `minimum` value should be considered exclusive. - - - Builds a constraint object for a keyword. - The for the schema object that houses this keyword. - - The set of other s that have been processed prior to this one. - Will contain the constraints for keyword dependencies. - - The . - A constraint object. - - - - Models a security requirement. - - - - - Models a security scheme. - - - - - Gets the type of security scheme. - - - - - Gets or sets the description. - - - - - Gets or sets the name. - - - - - Gets or sets the location of the API key. - - - - - Gets or sets the scheme. - - - - - Gets or sets the bearer token format. - - - - - Gets or sets the collection of OAuth flows. - - - - - Gets the OpenID Connect URL. - - - - - Gets or set extension data. - - - - - Creates a new - - The security scheme type - - - - Models a `$ref` to a security scheme. - - - - - The URI for the reference. - - - - - Gets or sets the summary. - - - - - Gets or sets the description. - - - - - Gets whether the reference has been resolved. - - - - - Creates a new - - The reference URI - - - - Creates a new - - The reference URI - - - - Defines the different security scheme locations. - - - - - Indicates the location is unknown. - - - - - Indicates the API key is located in the query. - - - - - Indicates the API key is located in a header. - - - - - Indicates the API key is located in a cookie. - - - - - Models a server. - - - - - Gets the URL of the server. - - - - - Gets or sets the description. - - - - - Gets or sets the variable map. - - - - - Gets or set extension data. - - - - - Creates a new - - The server URL - - - - Models a server variable. - - - - - Gets or sets an enumeration of string values to be used if the substitution options are from a limited set. - - - - - Gets the default value to use for substitution. - - - - - Gets or sets the description. - - - - - Gets or set extension data. - - - - - Creates a new - - The default value - - - - Models a tag. - - - - - Gets the tag name. - - - - - Gets or sets the tag description. - - - - - Gets or sets external documentation. - - - - - Gets or set extension data. - - - - - Creates a new - - The tag name - - - - Creates a new from a . - - The `JsonNode`. - The model. - Thrown when the JSON does not accurately represent the model. - - - diff --git a/Graeae.Models/OpenApiDocument.cs b/Graeae.Models/OpenApiDocument.cs index 8f39a45..2316109 100644 --- a/Graeae.Models/OpenApiDocument.cs +++ b/Graeae.Models/OpenApiDocument.cs @@ -52,7 +52,7 @@ public class OpenApiDocument : IBaseDocument /// /// Gets or sets the server collection. /// - public IEnumerable? Servers { get; set; } + public IReadOnlyList? Servers { get; set; } /// /// Gets or sets the paths collection. /// @@ -68,11 +68,11 @@ public class OpenApiDocument : IBaseDocument /// /// Gets or sets the security requirements collection. /// - public IEnumerable? Security { get; set; } + public IReadOnlyList? Security { get; set; } /// /// Gets or sets the tags. /// - public IEnumerable? Tags { get; set; } + public IReadOnlyList? Tags { get; set; } /// /// Gets or sets external documentation. /// diff --git a/Graeae.Models/OpenApiExtensions.cs b/Graeae.Models/OpenApiExtensions.cs new file mode 100644 index 0000000..ba99587 --- /dev/null +++ b/Graeae.Models/OpenApiExtensions.cs @@ -0,0 +1,57 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using Json.Pointer; +using Json.Schema; + +namespace Graeae.Models; + +/// +/// Provides extensions on various OpenAPI types. +/// +public static class OpenApiExtensions +{ + /// + /// Validates a payload against the schema at the indicated location. + /// + /// The OpenAPI document. + /// The payload to validate. + /// The location within the document where the schema can be found. + /// (optional) The evaluation options. This should be the same options object used to initialize the OpenAPI document. + /// The evaluation options if the schema was found; otherwise null. + public static EvaluationResults? EvaluatePayload(this OpenApiDocument openApiDocument, JsonNode? payload, JsonPointer schemaLocation, EvaluationOptions? options = null) + { + var schema = openApiDocument.Find(schemaLocation); + + return schema?.Evaluate(payload, options); + } + + /// + /// Validates a payload against the schema at the indicated location. + /// + /// The OpenAPI document. + /// The payload to validate. + /// The location within the document where the schema can be found. + /// (optional) The evaluation options. This should be the same options object used to initialize the OpenAPI document. + /// The evaluation options if the schema was found; otherwise null. + public static EvaluationResults? EvaluatePayload(this OpenApiDocument openApiDocument, JsonDocument payload, JsonPointer schemaLocation, EvaluationOptions? options = null) + { + var schema = openApiDocument.Find(schemaLocation); + + return schema?.Evaluate(payload, options); + } + + /// + /// Validates a payload against the schema at the indicated location. + /// + /// The OpenAPI document. + /// The payload to validate. + /// The location within the document where the schema can be found. + /// (optional) The evaluation options. This should be the same options object used to initialize the OpenAPI document. + /// The evaluation options if the schema was found; otherwise null. + public static EvaluationResults? EvaluatePayload(this OpenApiDocument openApiDocument, JsonElement payload, JsonPointer schemaLocation, EvaluationOptions? options = null) + { + var schema = openApiDocument.Find(schemaLocation); + + return schema?.Evaluate(payload, options); + } +} \ No newline at end of file diff --git a/Graeae.Models/Operation.cs b/Graeae.Models/Operation.cs index 0f62dc1..e5cdaff 100644 --- a/Graeae.Models/Operation.cs +++ b/Graeae.Models/Operation.cs @@ -30,7 +30,7 @@ public class Operation : IRefTargetContainer /// /// Gets or sets the tags. /// - public IEnumerable? Tags { get; set; } + public IReadOnlyList? Tags { get; set; } /// /// Gets or sets the summary. /// @@ -50,7 +50,7 @@ public class Operation : IRefTargetContainer /// /// Gets or sets the parameters. /// - public IEnumerable? Parameters { get; set; } + public IReadOnlyList? Parameters { get; set; } /// /// Gets or sets the request body. /// @@ -70,11 +70,11 @@ public class Operation : IRefTargetContainer /// /// Gets or sets the security requirements. /// - public IEnumerable? Security { get; set; } + public IReadOnlyList? Security { get; set; } /// /// Gets or sets the server collection. /// - public IEnumerable? Servers { get; set; } + public IReadOnlyList? Servers { get; set; } /// /// Gets or set extension data. /// diff --git a/Graeae.Models/PathItem.cs b/Graeae.Models/PathItem.cs index be23e1f..fb4d741 100644 --- a/Graeae.Models/PathItem.cs +++ b/Graeae.Models/PathItem.cs @@ -70,11 +70,11 @@ public class PathItem : IRefTargetContainer /// /// Gets or sets the collection of servers. /// - public IEnumerable? Servers { get; set; } + public IReadOnlyList? Servers { get; set; } /// /// Gets or sets the collection of parameters. /// - public IEnumerable? Parameters { get; set; } + public IReadOnlyList? Parameters { get; set; } /// /// Gets or set extension data. /// diff --git a/Graeae.Models/SerializationExtensions.cs b/Graeae.Models/SerializationExtensions.cs index ab8a20b..d412682 100644 --- a/Graeae.Models/SerializationExtensions.cs +++ b/Graeae.Models/SerializationExtensions.cs @@ -28,7 +28,7 @@ public static T Expect(this JsonObject obj, string propertyName, string objec return factory(value); } - public static IEnumerable? MaybeArray(this JsonObject obj, string propertyName, Func factory) + public static IReadOnlyList? MaybeArray(this JsonObject obj, string propertyName, Func factory) { if (!obj.TryGetPropertyValue(propertyName, out var array)) return null; if (array is not JsonArray map) diff --git a/Graeae.Models/ServerVariable.cs b/Graeae.Models/ServerVariable.cs index 93874ab..d784216 100644 --- a/Graeae.Models/ServerVariable.cs +++ b/Graeae.Models/ServerVariable.cs @@ -20,7 +20,7 @@ public class ServerVariable : IRefTargetContainer /// /// Gets or sets an enumeration of string values to be used if the substitution options are from a limited set. /// - public IEnumerable? Enum { get; set; } + public IReadOnlyList? Enum { get; set; } /// /// Gets the default value to use for substitution. /// diff --git a/README.md b/README.md index 762d415..928835e 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,29 @@ var asText = YamlSerializer.Serialize(openApiDoc); During initialization, if the document contains references that cannot be resolved, a `RefResolutionException` will be thrown. +### Payload Validation + +To validate a payload against a JSON Schema within your OpenAPI document, use the `.EvaluatePayload()` extension method. + +```c# +var payload = JsonNode.Parse(""); +var schemaComponentLocation = JsonPointer.Parse("/pointer/to/schema"); +var results = openApiDoc.EvaluatePayload(payload, schemaComponentLocation); +``` + +If your schema is under the `paths` section in the OpenAPI document, it may be easier and more readable to get the pointer using the `JsonPointer.Create()` method and passing the individual segments. This avoids having to escape forward slashes `/`. + +```c# +var schemaInPathLocation = JsonPointer.Create("paths", "/pets/{petId}", "get", "parameters", 0 , "schema"); +``` + +Of course, if the path is well-known at dev time, you can also just access it directly: + +```c# +var schemaInPath = openApiDoc.Paths["/pets/{petId}"].Get.Parameters[0].Schema; +var results = schemaInPath.Evaluate(payload); +``` + ### OpenAPI 3.0.x and JSON Schema Draft 4 To support OpenAPI v3.0.x, you'll need to enable JSON Schema draft 4 support first. To do that, add this to your app initialization: diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..b17118d --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,13 @@ +[0.3.1](https://github.com/gregsdennis/Graeae/pull/10) + +- Added `.EvaluatePayload()` extension on `OpenApiDocument`. +- Updated array members from `IEnumerable` to `IReadOnlyList` to enable indexer access. + +[0.3.0](https://github.com/gregsdennis/Graeae/pull/6) + +- Updated _JsonSchema.Net_. +- Set up for Native AOT. + +[0.2.1](https://github.com/gregsdennis/Graeae/pull/4) + +Automatically register draft 4 `type` keyword. \ No newline at end of file