Skip to content

Instantly share code, notes, and snippets.

@Hardtack
Created January 23, 2016 09:32
Show Gist options
  • Save Hardtack/8baeba02bd509e489f38 to your computer and use it in GitHub Desktop.
Save Hardtack/8baeba02bd509e489f38 to your computer and use it in GitHub Desktop.
Marshmallow JSON Schema for Formencode schema
import datetime
import decimal
import uuid
from marshmallow import Schema, fields
from formencode import validators as v
from formencode.api import Validator as FormencodeValidator, NoDefault
from formencode.schema import Schema as FormencodeSchema
# From https://github.com/fuhrysteve/marshmallow-jsonschema/blob/master/marshmallow_jsonschema/base.py
TYPE_MAP = {
dict: {
'type': 'object',
},
list: {
'type': 'array',
},
datetime.time: {
'type': 'string',
'format': 'time',
},
datetime.timedelta: {
# TODO explore using 'range'?
'type': 'string',
},
datetime.datetime: {
'type': 'string',
'format': 'date-time',
},
datetime.date: {
'type': 'string',
'format': 'date',
},
uuid.UUID: {
'type': 'string',
'format': 'uuid',
},
str: {
'type': 'string',
},
bytes: {
'type': 'string',
},
decimal.Decimal: {
'type': 'number',
'format': 'decimal',
},
set: {
'type': 'array',
},
tuple: {
'type': 'array',
},
float: {
'type': 'number',
'format': 'float',
},
int: {
'type': 'number',
'format': 'integer',
},
bool: {
'type': 'boolean',
},
}
class JSONSchema(Schema):
type = fields.Constant('object')
properties = fields.Method('get_properties')
required = fields.Method('get_required')
_type_mapping = {
v.ByteString: bytes,
v.StringBool: str,
v.Bool: bool,
v.Int: int,
v.Number: float,
v.UnicodeString: str,
v.Regex: str,
}
def get_properties(self, schema: FormencodeSchema):
fields = schema.fields
properties = {}
for name, validator in fields.items():
properties[name] = self._convert_validator(validator)
return properties
def _convert_type(self, python_type):
return TYPE_MAP[python_type]
def _convert_validator(self, validator: FormencodeValidator):
for validator_class, python_type in self._type_mapping.items():
if isinstance(validator, validator_class):
return self._convert_type(python_type)
def get_required(self, schema: FormencodeSchema):
fields = schema.fields
required = []
for name, validator in fields.items():
if self._is_required(validator):
required.append(name)
return required
def _is_required(self, validator: FormencodeValidator):
if validator.not_empty:
return True
if validator.if_missing is NoDefault:
return True
return False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment