openapi3-3.2.4: OpenAPI 3.0 data model
MaintainerNickolay Kudasov <nickolay@getshoptv.com>
Stabilityexperimental
Safe HaskellSafe-Inferred
LanguageHaskell2010

Data.OpenApi.Schema.Validation

Description

Validate JSON values with Swagger Schema.

Synopsis

How to use validation

This module provides helpful functions for JSON validation. These functions are meant to be used in test suites for your application to ensure that JSON respresentation for your data corresponds to schemas you're using for the Swagger specification.

It is recommended to use validation functions as QuickCheck properties (see http://hackage.haskell.org/package/QuickCheck).

Examples

>>> validateToJSON "hello"
[]
>>> validateToJSON False
[]
>>> newtype Nat = Nat Integer deriving Generic
>>> instance ToJSON Nat where toJSON (Nat n) = toJSON n
>>> instance ToSchema Nat where declareNamedSchema proxy = genericDeclareNamedSchema defaultSchemaOptions proxy & mapped.minimum_ ?~ 0
>>> validateToJSON (Nat 10)
[]
>>> validateToJSON (Nat (-5))
["value -5.0 falls below minimum (should be >=0.0)"]

Validating Maybe

Because Maybe a has the same schema as a, validation generally fails for null JSON:

>>> validateToJSON (Nothing :: Maybe String)
["expected JSON value of type OpenApiString"]
>>> validateToJSON ([Just "hello", Nothing] :: [Maybe String])
["expected JSON value of type OpenApiString"]
>>> validateToJSON (123, Nothing :: Maybe String)
["expected JSON value of type OpenApiString"]

However, when Maybe a is a type of a record field, validation takes required property of the Schema into account:

>>> data Person = Person { name :: String, age :: Maybe Int } deriving Generic
>>> instance ToJSON Person
>>> instance ToSchema Person
>>> validateToJSON (Person "Nick" (Just 24))
[]
>>> validateToJSON (Person "Nick" Nothing)
[]

JSON validation

type ValidationError = String Source #

Validation error message.

Using ToJSON and ToSchema

validatePrettyToJSON :: forall a. (ToJSON a, ToSchema a) => a -> Maybe String Source #

Validate ToJSON instance matches ToSchema for a given value. This can be used with QuickCheck to ensure those instances are coherent:

validateToJSON (x :: Int) == []

NOTE: validateToJSON does not perform string pattern validation. See validateToJSONWithPatternChecker.

See renderValidationErrors on how the output is structured.

validateToJSON :: forall a. (ToJSON a, ToSchema a) => a -> [ValidationError] Source #

Variant of validatePrettyToJSON with typed output.

validateToJSONWithPatternChecker :: forall a. (ToJSON a, ToSchema a) => (Pattern -> Text -> Bool) -> a -> [ValidationError] Source #

Validate ToJSON instance matches ToSchema for a given value and pattern checker. This can be used with QuickCheck to ensure those instances are coherent.

For validation without patterns see validateToJSON. See also: renderValidationErrors.

renderValidationErrors :: forall a. (ToJSON a, ToSchema a) => (a -> [ValidationError]) -> a -> Maybe String Source #

Pretty print validation errors together with actual JSON and Swagger Schema (using encodePretty).

>>> import Data.Aeson as Aeson
>>> import Data.Foldable (traverse_)
>>> import GHC.Generics
>>> data Phone = Phone { value :: String } deriving (Generic)
>>> data Person = Person { name :: String, phone :: Phone } deriving (Generic)
>>> instance ToJSON Person where toJSON p = object [ "name" Aeson..= name p ]
>>> instance ToSchema Phone
>>> instance ToSchema Person
>>> let person = Person { name = "John", phone = Phone "123456" }
>>> traverse_ putStrLn $ renderValidationErrors validateToJSON person
Validation against the schema fails:
  * property "phone" is required, but not found in "{\"name\":\"John\"}"

JSON value:
{
    "name": "John"
}

Swagger Schema:
{
    "properties": {
        "name": {
            "type": "string"
        },
        "phone": {
            "$ref": "#/components/schemas/Phone"
        }
    },
    "required": [
        "name",
        "phone"
    ],
    "type": "object"
}

Swagger Description Context:
{
    "Phone": {
        "properties": {
            "value": {
                "type": "string"
            }
        },
        "required": [
            "value"
        ],
        "type": "object"
    }
}

Using Value and Schema

validateJSON :: Definitions Schema -> Schema -> Value -> [ValidationError] Source #

Validate JSON ExpressionOrValue against Swagger Schema.

validateJSON mempty (toSchema (Proxy :: Proxy Int)) (toJSON (x :: Int)) == []

NOTE: validateJSON does not perform string pattern validation. See validateJSONWithPatternChecker.

validateJSONWithPatternChecker :: (Pattern -> Text -> Bool) -> Definitions Schema -> Schema -> Value -> [ValidationError] Source #

Validate JSON ExpressionOrValue agains Swagger ToSchema for a given value and pattern checker.

For validation without patterns see validateJSON.