Skip to content

Instantly share code, notes, and snippets.

@Martin91
Last active May 17, 2018 10:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Martin91/a2aad34cedf4bfce94b21c9523fb1fd4 to your computer and use it in GitHub Desktop.
Save Martin91/a2aad34cedf4bfce94b21c9523fb1fd4 to your computer and use it in GitHub Desktop.
param convert according to json schema in python
from lib.errors import TypeConvertInvalid
SIMPLE_VALUE_TYPES = [str, int, float]
BOOLABLE_TYPES = SIMPLE_VALUE_TYPES[:]
BOOLABLE_TYPES.append(bool)
def convert(value, convert_func, parse_path, convertable_types=SIMPLE_VALUE_TYPES):
if type(value) in convertable_types:
try:
return convert_func(value)
except ValueError:
pass
error_message = '%s: %s could not be converted' % (type(value), parse_path)
raise TypeConvertInvalid(error_message)
def convert_to_boolean(value, parse_path):
if str(value).lower() == 'true':
return True
if str(value).lower() == 'false':
return False
return convert(value=value,
convert_func=bool,
parse_path=parse_path,
convertable_types=BOOLABLE_TYPES)
def handle_list_param(param, schema, parse_path):
if type(param) is not list:
raise TypeConvertInvalid('%s: %s is not an list' % (type(param), parse_path))
items_schema = schema.get('items')
if items_schema:
new_param = []
for index, ele in enumerate(param):
_parse_path = parse_path + '[%d]' % index
new_param.append(paramsconvert(ele, items_schema, parse_path=_parse_path))
return new_param
def handle_object_params(param, schema, parse_path):
if type(param) is not dict:
raise TypeConvertInvalid('%s: %s is not an dict' % (type(param), parse_path))
properties = schema.get('properties')
if properties:
new_param = {}
for key in properties.keys():
value = param.get(key)
if value is not None:
_parse_path = parse_path + '[%s]' % key
new_param[key] = paramsconvert(value, properties[key], parse_path=_parse_path)
return new_param
def paramsconvert(param, schema, parse_path='param'):
param_type = schema['type']
if param_type == 'object':
result = handle_object_params(param=param, schema=schema, parse_path=parse_path)
if result: return result
elif param_type == 'string':
return convert(value=param, convert_func=str, parse_path=parse_path)
elif param_type == 'int':
return convert(value=param, convert_func=int, parse_path=parse_path)
elif param_type == 'number':
return convert(value=param, convert_func=float, parse_path=parse_path)
elif param_type == 'boolean':
return convert_to_boolean(value=param, parse_path=parse_path)
elif param_type == 'array':
result = handle_list_param(param=param, schema=schema, parse_path=parse_path)
if result: return result
return param
from unittest import TestCase
from lib.errors import TypeConvertInvalid
from lib.paramsconvert import paramsconvert
class ParamsConvertTest(TestCase):
def test_simple_string_schema(self):
schema = {'type': 'string'}
param = 'hello'
self.assertEqual(paramsconvert(param, schema), param)
def test_simple_string_but_a_integer_schema(self):
schema = {'type': 'string'}
param = 1
self.assertEqual(paramsconvert(param, schema), '1')
def test_simple_string_but_a_dict_schema(self):
schema = {'type': 'string'}
param = {'a': 1}
with self.assertRaises(TypeConvertInvalid):
paramsconvert(param, schema)
def test_simple_int_schema(self):
schema = {'type': 'int'}
param = '1'
self.assertEqual(paramsconvert(param, schema), 1)
def test_simple_int_but_a_array_schema(self):
schema = {'type': 'int'}
param = []
with self.assertRaises(TypeConvertInvalid):
paramsconvert(param, schema)
def test_simple_number_schema(self):
schema = {'type': 'number'}
param = '1.2'
self.assertEqual(paramsconvert(param, schema), 1.2)
def test_simple_boolean_with_true_schema(self):
schema = {'type': 'boolean'}
param = 'True'
self.assertEqual(paramsconvert(param, schema), True)
def test_simple_boolean_with_false_schema(self):
schema = {'type': 'boolean'}
param = 'false'
self.assertEqual(paramsconvert(param, schema), False)
def test_simple_boolean_but_a_dict_schema(self):
schema = {'type': 'boolean'}
param = {}
with self.assertRaises(TypeConvertInvalid):
paramsconvert(param, schema)
def test_simple_array_without_items_type_declaration(self):
schema = {'type': 'array'}
param = [1, 2, 3, 'a', 'b', 'c']
self.assertEqual(paramsconvert(param, schema), param)
def test_simple_array_with_items_type_declaration(self):
schema = {
'type': 'array',
'items': {
'type': 'int'
}
}
param = ['1', '2', '3']
self.assertEqual(paramsconvert(param, schema), [1, 2, 3])
def test_simple_array_but_in_fact_a_simple_string(self):
schema = {
'type': 'array',
'items': {
'type': 'int'
}
}
param = ''
with self.assertRaises(TypeConvertInvalid):
paramsconvert(param, schema)
def test_complex_object_schema(self):
schema = {
'type': 'object',
'properties': {
'a': {'type': 'int'},
'b': {'type': 'string'},
'c': {
'type': 'object',
'properties': {
'd': {'type': 'boolean'},
'e': {
'type': 'array',
'items': {'type': 'int'}
},
'f': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'g': {'type': 'number'}
}
}
}
}
}
}
}
param = {
'a': '1',
'b': 'world',
'c': {
'd': 'true',
'e': ['1', '2', '3'],
'f': [{
'g': '1.332',
}, {
'g': '3.2019'
}]
}
}
expect_param = {
'a': 1,
'b': 'world',
'c': {
'd': True,
'e': [1, 2, 3],
'f': [{
'g': 1.332,
}, {
'g': 3.2019
}]
}
}
self.assertEqual(paramsconvert(param, schema), expect_param)
def test_complex_object_schema_with_incorrect_structure(self):
schema = {
'type': 'object',
'properties': {
'a': {'type': 'int'},
'b': {'type': 'string'},
'c': {
'type': 'object',
'properties': {
'd': {'type': 'boolean'},
'e': {
'type': 'array',
'items': {'type': 'int'}
},
'f': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'g': {'type': 'number'}
}
}
}
}
}
}
}
param = {
'a': '1',
'b': 'world',
'c': {
'e': {},#['1', '2', '3'],
'f': [{}]
}
}
with self.assertRaises(TypeConvertInvalid):
paramsconvert(param, schema)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment