JsonSchema and OpenAPI tools for python.
- Validation builder for json schema
- Custom string formatters support
- Full JsonSchema draft-7 support
- Support for JsonReferences, $anchor
- Dataclass generation from OpenAPI schema
- Great performance
With pip,
pip install opyapi
or through poetry
poetry add opyapi
It is recommended to get familiar with json-schema if you haven't yet. Understanding Json Schema is a great place to start and learn Json Schema's basics
Library can be used to validate data, against defined json-schema like so:
from opyapi import validate
assert validate(
{"name": "Test", "age":12},
{
"type": "object",
"properties": {
"name": {
"type": "string",
},
"age": {
"type": "integer",
}
}
}
)
Validating documents against complex schemas is also possible, please consider the following example with json references:
from opyapi import validate
schema = {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 2,
},
"email": {
"$ref": "#/$defs/email"
}
},
"$defs": {
"email": {
"type": "string",
"format": "email"
}
}
}
validate({"name": "Bob", "email": "bob@test.com"}, schema)
from opyapi import StringFormat, validate
import re
def my_format_validator(value: str) -> str:
if re.match("^my-", value):
return value
raise ValueError(f"Could not validate {value}")
StringFormat["my-format"] = my_format_validator
validate("my-test", {"type": "string", "format": "my-format"}) # passes
validate("test", {"type": "string", "format": "my-format"}) # fails
In the above example
opyapi.StringFormat
is used to register new custom format, which is recognised during validation.
There are scenarios where same validator should be used multiple times,
in these scenarios to improve performance it is better to use build_validator_for
which returns a validator function for the passed schema:
from opyapi import build_validator_for
my_validator = build_validator_for({
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 2,
},
"email": {
"type": "string",
"format": "email",
}
},
})
assert my_validator({"name": "Bob", "email": "bob@email.com"})
opyapi
provides versatile error package, which is really simple to use. You are only required to define try/except
block within you can catch one of the errors defined in the package depending on your scenario.
from opyapi import build_validator_for
from opyapi.errors import ValidationError
my_validator = build_validator_for({
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 2,
},
"email": {
"type": "string",
"format": "email",
}
},
})
try:
my_validator({"name": "Bob", "email": "invalid"})
except ValidationError as e:
print(f"Validation failed from the reason: {e}")
The following graph represents exception used in opyapi
.
All exceptions are part of opyapi.errors
module.
ValueError
┗━ ValidationError
┣━ TypeValidationError
┣━ EnumValidationError
┣━ FormatValidationError
┣━ ItemsValidationError
┃ ┣━ UniqueItemsValidationError
┃ ┣━ AdditionalItemsValidationError
┃ ┣━ MinimumItemsValidationError
┃ ┗━ MaximumItemsValidationError
┣━ MultipleOfValidationError
┣━ ComparisonValidationError
┃ ┣━ EqualityValidationError
┃ ┗━ RangeValidationError
┃ ┣━ MinimumValidationError
┃ ┣━ MaximumValidationError
┃ ┣━ ExclusiveMinimumValidationError
┃ ┗━ ExclusiveMaximumValidationError
┗━ ObjectValidationError
┣━ PropertyValidationError
┃ ┣━ RequiredPropertyValidationError
┃ ┣━ PropertyValueValidationError
┃ ┣━ PropertyNameValidationError
┃ ┗━ AdditionalPropertiesValidationError
┣━ ObjectSizeValidationError
┃ ┣━ MinimumPropertiesValidationError
┃ ┗━ MaximumPropertiesValidationError
┗━ DependencyValidationError
Generic validation error.
Raised when passed type does not conform type defined in the schema.
Can be triggered by following example schema:
{ "type": "integer" }
Raised when value does not conform enum definition.
Can be triggered by following example schema:
{ "enum": ["integer", "string", "boolean"] }
Raised when value does not conform defined format in string schema.
Can be triggered by following example schema:
{ "type": "string", "format": "date-time" }
Generic Exception raised when validation of an array fails for some reason.
Raised when items in an array are expected to be unique but passed value does not conform the requirement.
This exception extends generic opyapi.errors.ItemsValidationError
exception.
Can be triggered by following example schema:
{ "type": "array", "uniqueItems": true }
Raised when additional items in an array either does not conform the schema or are not expected.
This exception extends generic opyapi.errors.ItemsValidationError
exception.
Can be triggered by the following schema:
{ "type": "array", "items": [ {"type": "string"}, {"type": "integer"} ], "additionalItems": false }
Raised when number of items in an array does not conform maximum or minimum items specified in schema.
This exception extends generic opyapi.errors.ItemsValidationError
exception.
Can be triggered by following example schema:
{ "type": "array", "minimumItems": 2, "MaximumItems": 10 }
Raised when validated number is not multiplication of passed value.
Can be triggered by following example schema:
{ "type": "numerical", "multipleOf": 2 }
Raised when comparison operation fails. This is a generic exception used by other comparison errors.
Raised when validated value is not the same as defined expected value. This exception extends opyapi.errors.ComparisonValidationError
.
Can be triggered by following example schema:
{ "const": "test" }
Raised when (exclusive) minimum, (exclusive) maximum comparisons fail. This exception extends opyapi.errors.ComparisonValidationError
.
opyapi.errors.MinimumValidationError
, opyapi.errors.MaximumValidationError
, opyapi.errors.ExclusiveMinimumValidationError
, opyapi.errors.ExclusiveMaximumValidationError
Raised when passed numerical (or integer) value is not within expected range defined in schema.
Can be triggered by the following example schema:
{ "type": "numerical", "minimum": 2 }
Generic exception raised when validation of an object fails for some reason.
Generic exception raised when validation of object's property fails for some reason.
This exception extends opyapi.errors.ObjectValidationError
exception.
Raised when required property is not present in passed object.
This exception extends opyapi.errors.PropertyValidationError
exception.
Can be triggered by the following example schema:
{ "type": "object", "properties": { "name" : {"type": "string"} }, "required": ["name"] }
Raised when property contains invalid value.
This exception extends opyapi.errors.PropertyValidationError
exception.
Can be triggered by the following example schema:
{ "type": "object", "properties": { "name" : {"type": "string"} } }
Raised when property's names does not conform defined schema.
This exception extends opyapi.errors.PropertyValidationError
exception.
Can be triggered by the following example schema:
{ "type": "object", "properties": { "name" : {"type": "string"} }, "propertyNames": { "pattern": "^x-" } }
Raised when additional properties are not allowed or set schema is not followed.
This exception extends opyapi.errors.PropertyValidationError
exception.
Can be triggered by the following example schema:
{ "type": "object", "properties": { "name" : {"type": "string"} }, "additionalProperties": false }
Generic exception raised when number of properties does not conform defined schema.
This exception extends opyapi.errors.ObjectValidationError
exception.
Generic exception raised when number of properties does not conform defined schema.
These exceptions extend opyapi.errors.ObjectSizeValidationError
exception.
Can be triggered by the following example schema:
{ "type": "object", "properties": { "name" : {"type": "string"} }, "minProperties": 2, "maxProperties": 10 }
Raised when dependent properties are defined in the schema but not provided in a passed object.
This exception extends opyapi.errors.ObjectValidationError
exception.
Can be triggered by the following example schema:
{ "type": "object", "properties": { "name" : {"type": "string"} }, "dependentRequired": { "name": ["first_name", "last_name"] } }
Validates passed object obj
, and if valid returns the object, otherwise raises a ValueError
exception.
from opyapi import validate
assert validate(
{"name": "Test", "age":12},
{
"type": "object",
"properties": {
"name": {
"type": "string",
},
"age": {
"type": "integer",
}
}
}
)
Creates validator function for passed json schema and returns it as a result.
from opyapi import build_validator_for
validator = build_validator_for({
"type": "object",
"properties": {
"name": {
"type": "string",
},
"age": {
"type": "integer",
}
}
})