Release v0.0.9.
JSON Schema and its Python implementation are wonderful tools for data validation.
JSL is a Python library that provides a DSL for describing JSON schemas.
Why? Well, JSON schemas, especially large ones, can be tiresome to write. The standard is not always intuitive and leaves some places to make a mistake – for instance, it is easy to mix maxItems keyword with maxLength, or to forget to set additionalProperties to false, and so on. The syntax is not very concise and sometimes schema definitions get clumsy and hard to comprehend.
The DSL allows you to define a JSON schema in the way similar to how you define a model using an ORM – using classes and fields and relying on some metaclass magic under the hood.
Let’s take a look at examples.
from jsl import Document, StringField, ArrayField, DocumentField, OneOfField
class Entry(Document):
name = StringField(required=True)
class File(Entry):
content = StringField(required=True)
class Directory(Entry):
content = ArrayField(OneOfField([
DocumentField(File, as_ref=True),
DocumentField('self')
]), required=True)
Directory.to_schema() will return the following schema:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"module.File": {
"type": "object",
"additionalProperties": false,
"required": [
"content",
"name"
],
"properties": {
"content": {"type": "string"},
"name": {"type": "string"}
}
},
"module.Directory": {
"type": "object",
"additionalProperties": false,
"required": [
"content",
"name"
],
"properties": {
"content": {
"type": "array",
"items": {
"oneOf": [
{"$ref": "#/definitions/module.File"},
{"$ref": "#/definitions/module.Directory"}
]
}
},
"name": {"type": "string"}
}
}
},
"$ref": "#/definitions/module.Directory"
}
A JSON schema from the official documentation, defined using JSL:
from jsl import Document, BooleanField, StringField, ArrayField, DocumentField, OneOfField, IntField
class DiskDevice(Document):
type = StringField(enum=['disk'], required=True)
device = StringField(pattern='^/dev/[^/]+(/[^/]+)*$', required=True)
class DiskUUID(Document):
type = StringField(enum=['disk'], required=True)
label = StringField(pattern='^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$',
required=True)
class NFS(Document):
type = StringField(enum=['nfs'], required=True)
remotePath = StringField(pattern='^(/[^/]+)+$', required=True)
server = OneOfField([
StringField(format='ipv4'),
StringField(format='ipv6'),
StringField(format='host-name'),
], required=True)
class TmpFS(Document):
type = StringField(enum=['tmpfs'], required=True)
sizeInMb = IntField(minimum=16, maximum=512, required=True)
class Schema(Document):
class Options(object):
schema_uri = 'http://json-schema.org/draft-04/schema#'
description = 'schema for an fstab entry'
storage = OneOfField([
DocumentField(DiskDevice, as_ref=True),
DocumentField(DiskUUID, as_ref=True),
DocumentField(NFS, as_ref=True),
DocumentField(TmpFS, as_ref=True),
], required=True)
fstype = StringField(enum=['ext3', 'ext4', 'btrfs'])
options = ArrayField(StringField(), min_items=1, unique_items=True)
readonly = BooleanField()
$ pip install jsl
A container for options. Its primary purpose is to create an instance of options for every instance of a Document.
All the arguments are the same and work exactly as for fields.DictField except these:
Parameters: |
|
---|
A document. Can be thought as a kind of fields.DictField, which properties are defined by the fields added to the document class.
It can be tuned using special Options attribute (see Options for available settings).
Example:
class User(Document):
class Options(object):
title = 'User'
description = 'A person who uses a computer or network service.'
login = StringField(required=True)
A metaclass for Document. It’s responsible for collecting fields and options, registering the document in the registry, making it the owner of nested DocumentField s and so on.
A class to be used by create_options(). Must be a subclass of Options.
alias of Options
Collects fields from the current class and its parent classes.
Return type: | a dictionary mapping field names to BaseField s |
---|
Collects options from the current class and its parent classes.
Return type: | a dictionary of options |
---|
Wraps options into a container class (see options_container).
Parameters: | options – a dictionary of options |
---|---|
Returns: | an instance of options_container |
A base class for fields in a JSL document.Document. Instances of this class may be added to a document to define its properties.
Parameters: | required – If the field is required, defaults to False. |
---|
A base class for fields that directly map to JSON Schema validator.
Parameters: |
|
---|
A reference to a nested document.
Parameters: |
|
---|
An array field.
Parameters: |
|
---|
A dictionary field.
Parameters: |
|
---|
Parameters: | field (BaseField) – a field to negate |
---|
Parameters: | fields (list of BaseField) – a list of fields, exactly one of which describes the data |
---|
Parameters: | fields (list of BaseField) – a list of fields, at least one of which describes the data |
---|
Parameters: | fields (list of BaseField) – a list of fields, all of which describe the data |
---|
A boolean field.
A string field.
Parameters: |
|
---|
An email field.
An IPv4 field.
An ISO 8601 formatted date-time field.
A URI field.
A URI field.
A number field.
Parameters: |
|
---|