Last active
May 17, 2018 10:05
-
-
Save Martin91/a2aad34cedf4bfce94b21c9523fb1fd4 to your computer and use it in GitHub Desktop.
param convert according to json schema in python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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