Skip to content

Validator

mattpolzin edited this page Jun 11, 2021 · 3 revisions

Validator

A validator that works by traversing an Encodable object and validating any values that match an included validation's type and pass that validation's predicate.

public final class Validator 

The default Validator will perform a set of default validations that catch OpenAPI Specification violations not possible (or inconvenient) to prevent using the Swift type-system.

Example

let document = OpenAPI.Document(...)
let validator = Validator()
try document.validate(using: validator)

// or, equivalently for the default validator:
try document.validate()

The default validations are

  • Operations must contain at least one response.

  • Document-level tag names are unique.

  • Parameters are unique within each Path Item.

  • Parameters are unique within each Operation.

  • Operation Ids are unique across the whole Document.

  • All JSONReferences that refer to components in this document can be found in the components dictionary.

If you want a Validator that won't perform any validations except the ones you add, use Validator.blank.

You can add validations to the validator using the validating() instance methods.

There are a few default validations that ship with OpenAPIKit but are not used unless explicitly added to a Validator. You can find these validations as static members of the Validation type.

Example

let document = OpenAPI.Document(...)
let validator = Validator()
    .validating(.documentContainsPaths)
    .validating(.pathsContainOperations)
try document.validate(using: validator)

At their core, all validations are values of the Validation type. You can create validations by initializing the Validation type directly but it is generally more convenient to add validations to a Validator using one of the convenience validating() methods that know how to construct Validation on your behalf.

For example, you can construct validation methods for simple equalities and inequalities by specifying the KeyPath from any OpenAPI type to the value you want to validate and then writing the equality/inequality that must succeed for the validation to pass.

Example

let validator = Validator()
    .validating(
        "API version is 2.0",
        check: \OpenAPI.Document.Info.version == "2.0"
)

You can add a where clause to any validation as long as the check and where clause both examine the same type (i.e. OpenAPI.Document.Info from the previous example and OpenAPI.Document from the next example).

The next example also uses given() in its where caluse. This allows you to dig into a value based on its KeyPath just like the previous example but you can use it for more complicated criteria than equality/inequality.

Finally, the next example also introduces the context access KayPath syntax in its check clause. This syntax allows you to access the entire OpenAPI Document that is being validated as \.document. It also gives you access to the current value being validated as \.subject and the current key path as \.codingPath.

Example

let validator = Validator()
    .validating(
        "At least two servers are specified if one of them is the test server.",
        check: \.document.servers.count >= 2,
        when: given(\OpenAPI.Document.servers) { servers in
            servers.map { $0.url.absoluteString }.contains("https://test.server.com")
        }
)

Context access, the given() method, and the inequality KeyPath syntax are all allowed in both the check and where clauses. Just keep in mind that if you omit information about the type of thing being validated in one clause (as you do when you access \.document) then you need to indicate the type (perhaps with a KeyPath that includes the full type as in \OpenAPI.Document.servers above) in the other clause so the type system knows what you are validating.

Initializers

init()

Creates the default Validator. Note that this Validator will perform the default validations. If you want a Validator that won't perform any validations except the ones you add, use Validator.blank.

public convenience init() 

The default validations are

  • Operations must contain at least one response.

  • Document-level tag names are unique.

  • Parameters are unique within each Path Item.

  • Parameters are unique within each Operation.

  • Operation Ids are unique across the whole Document.

  • All JSONReferences that refer to components in this document can be found in the components dictionary.

Properties

blank

A validator with no validation rules at all (not even the defaults).

public static var blank: Validator 

Methods

validating(_:)

Add a validation to be performed.

public func validating<T: Encodable>(_ validation: Validation<T>) -> Self 

validating(_:)

Add a validation to be performed.

public func validating<T: Encodable>(
        _ validate: @escaping (ValidationContext<T>) -> [ValidationError]
    ) -> Self 

Parameters

  • validate: A function taking values of type T and validating them. This function should return an array of all validation failures. ValidationError is a good general purpose error for this use-case.

validating(_:when:)

Add a validation to be performed.

public func validating<T: Encodable>(
        _ validate: @escaping (ValidationContext<T>) -> [ValidationError],
        when predicate: @escaping (ValidationContext<T>) -> Bool
    ) -> Self 

Parameters

  • validate: A function taking values of type T and validating them. This function should return an array of all validation failures. ValidationError is a good general purpose error for this use-case.
  • predicate: A function returning true if this validator should run against the given value.

validating(_:check:)

Given the description of the correct & valid state being asserted, create a validation function and add it to the Validator.

public func validating<T: Encodable>(
        _ description: String,
        check validate: @escaping (ValidationContext<T>) -> Bool
    ) -> Self 

Parameters

  • description: The description of the correct state described by the assertion.
  • validate: The function called to assert a condition. The function should return false if the validity check has failed or true if everything is valid.

validating(_:check:when:)

Given the description of the correct & valid state being asserted, create a validation function and add it to the Validator.

public func validating<T: Encodable>(
        _ description: String,
        check validate: @escaping (ValidationContext<T>) -> Bool,
        when predicate: @escaping (ValidationContext<T>) -> Bool
    ) -> Self 

Parameters

  • description: The description of the correct state described by the assertion.
  • validate: The function called to assert a condition. The function should return false if the validity check has failed or true if everything is valid.
  • predicate: A condition that must be met for this validation to be applied.
Types
Protocols
Global Functions
Extensions
Clone this wiki locally