Skip to main content

Simple schema validator

coverage

A dead-simple utility that validates if object has a certain structure. Used in some of our projects.

Basic usage

pip install simple_schema_validator

An example:

Lets say we have an API that returns the following data:

{
  "user": 1,
  "profile": {
    "email": "some@user.com",
    "name": "Some User",
    "age": 20
  },
  "tokens": {
    "jwt": "...",
    "refresh": "...",
    "firebase": "...",
  }
}

And we are writing a simple integration test, that wants to assure the response has a certain structure.

Then we can use the schema validator like so:

from simple_schema_validator import schema_validator

data = get_data_from_api()

schema = {
  'user': Any,
  'profile': {
    'email': Any,
    'name': Any,
    'age': Any
  },
  'tokens': {
    'jwt': Any,
    'refresh': Any,
    'firebase': Any
  }
}

validation = schema_validator(schema, data)

if not validation:
    print(f'Keys in data, but not in schema: {validation.additional_keys}')
    print(f'Keys in schema, but not in data: {validation.missing_keys}')
    print(f'Keys with different type from schema {validation.type_errors}')
  • missing_keys are those keys that are required in the schema, but not found in data.
  • additional_keys are those keys present in data, but not required by the schema.
  • validation_errors are those keys, that are having a different type in data, from the defined in schema.

Nested keys are represented with "dot" notation - profile.email, tokens.jwt, etc.

Type checking

The util supports simple schema type checking.

Currently, the supported types in the schema are:

  • int
  • float
  • str
  • bool
  • typing.Any (from Python typing library)
  • simple_schema_validator.types.Optional (custom type, define in the package)

If the type is Any, no type checking is done.

If there's a type mismatch, the errors are placed in the type_errors attribute of the result, which is a list of type errors.

The general format of a single type error is:

{
  'path': 'the.path.to.the.value.in.data',
  'expected': the_expected_type_as_defined_in_the_schema,
  'actual': the_actual_type_of_the_value
}

Here's an example:

from simple_schema_validator import schema_validator, types


schema = {
  'user': str,
  'profile': {
    'email': str,
    'name': str,
    'age': int
  },
  'tokens': {
    'jwt': str,
    'refresh': str,
    'firebase': str
  }
}

data = {
  'user': 'Some User',
  'profile': {
    'email': 'someuser@hacksoft.io',
    'name': 'Some User',
    'age': "29"
  },
  'tokens': {
    'jwt': 'some token value',
    'refresh': 'some token value',
    'firebase': 'some token value'
  }

}

result = schema_validator(schema, data)


assert bool(result) is False
assert result.type_errors == [{'path': 'profile.age', 'expected': int, 'actual': str}]

Optional types

The schema validator support optional types.

You can do the following:

from simple_schema_validator import schema_validator, types

schema = {
  'a': types.Optional[int]
}

data_1 = {
  'a': None
}

data_2 = {
  'a': 1
}

data_3 = {
  'a': 'some_string'
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is True
assert bool(schema_validator(schema, data_3)) is False

Additionally, you can define optional branches in the schema:

from simple_schema_validator import schema_validator, types

schema = {
  'a': types.Optional[{
    'b': int
  }]
}

data_1 = {
  'a': None
}

data_2 = {
  'a': 1
}

data_3 = {
  'a': {
    'b': 1
  }
}

data_4 = {
  'a': {
    'b': 'some_string'
  }
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is False
assert bool(schema_validator(schema, data_3)) is True
assert bool(schema_validator(schema, data_4)) is False

You can use it with optional lists aswell:

from simple_schema_validator import schema_validator, types

schema = {
  'a': types.Optional[[int]]
}

data_1 = {
  'a': None
}

data_2 = {
  'a': 1
}

data_3 = {
  'a': [1, 2, 3]
}

data_4 = {
  'a': ['some_string']
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is False
assert bool(schema_validator(schema, data_3)) is True
assert bool(schema_validator(schema, data_4)) is False

List types

The schema validator support list types.

You can do the following:

from simple_schema_validator import schema_validator, types

schema = {
  'a': types.List[int]
}

data_1 = {
  'a': [1, 2, 3]
}

data_3 = {
  'a': ['some_string']
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is False

Recursive schemas

The schema validator support type checking for schemas in list.

You can do the following:

from simple_schema_validator import schema_validator, types

schema = {
  'a': [{'b': int}]
}

data_1 = {
  'a': [{'b': 1}]
}

data_2 = {
  'a': [{'b': 'some_string'}]
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is False
from simple_schema_validator import schema_validator, types

schema = {
  'a': [{'b': [int]}]
}

data_1 = {
  'a': [{'b': [1]}]
}

data_2 = {
  'a': [{'b': [1, 2, 3]}]
}

data_3 = {
  'a': [{'b': ['some_string']}]
}

data_4 = {
  'a': [{'b': [1, 'some_string']}]
}

data_5 = {
  'a': [{'b': ['some_string', 'other_string']}]
}

data_6 = {
  'a': [{'b': ['some_string', 1]}]
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is True
assert bool(schema_validator(schema, data_3)) is False
assert bool(schema_validator(schema, data_4)) is False
assert bool(schema_validator(schema, data_5)) is False
assert bool(schema_validator(schema, data_6)) is False

You can do the same with optional branches aswell:

from simple_schema_validator import schema_validator, types

schema = {
  'a': [{'b': types.Optional[int]}]
}

data_1 = {
  'a': [{
    'b': {
      'c': 1,
      'd': 2
    }
  }]
}

data_2 = {
  'a': [{'b': 'some_string'}]
}

assert bool(schema_validator(schema, data_1)) is True
assert bool(schema_validator(schema, data_2)) is False

Examples

For examples, check the examples folder or the tests for the project.

Metadata

Release files for simple-schema-validator 0.0.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for simple-schema-validator 0.0.9
File Size Uploaded Provenance
simple_schema_validator-0.0.9.tar.gz 8.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for simple-schema-validator 0.0.9
File Interpreter ABI Platform
simple_schema_validator-0.0.9-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 17.1 kB

Release files / simple_schema_validator-0.0.9.tar.gz

Download URL simple_schema_validator-0.0.9.tar.gz
Size 8.0 kB
Tags Source
SHA-256 checksum
How to use checksums
81382f2292ebbd5f475b232beb25002f345794ae4668603eb48435534dbeca02
BLAKE2b-256 checksum
How to use checksums
2cda7cb82756fc52eea3599142b72fa6467325b0c8eaac546d950f4ccb1b29d1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.7

Release files / simple_schema_validator-0.0.9-py2.py3-none-any.whl

Download URL simple_schema_validator-0.0.9-py2.py3-none-any.whl
Size 9.1 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
d72af6f10b1af94c612bf6658868801e47d5fd55114473f00a1e56ad21504373
BLAKE2b-256 checksum
How to use checksums
2bdf82a61d86ac080cb7d8a9fb01e82590cdb5ce9515f172aa95aa33e72dbc5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.12.1 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.7

Security for simple-schema-validator 0.0.9

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page