class Code(object):
MSG = { }
@classmethod
def api_resp(cls, code=0, msg=None, data=None):
if codeis None:
reason = cls.MSG.get(result, '')
return ApiResp(result, reason, resp)
def safe_int(val):
if isinstance(val, (int, long)):
return val
if isinstance(val, basestring):
val = val.strip()
try:
if isinstance(val, basestring) and "." in val:
return int(float(val))
return int(val)
except Exception:
raise ValidateException(Code.invalid_params, 'safe_int error ,'
'val:{0}'.format(val))
def safe_float(val):
if isinstance(val, float):
return val
if isinstance(val, (int, long)):
return float(val)
if isinstance(val, basestring):
val = val.strip()
try:
return float(val)
except Exception:
raise ValidateException(Code.invalid_params, 'safe_float error ,'
'val:{0}'.format(val))
def safe_str(val, encodeing="utf-8"):
try:
if not isinstance(val, basestring):
return str(val)
if isinstance(val, unicode):
return val.encode(encodeing, "replace")
return val
except Exception:
raise ValidateException(Code.invalid_params, 'safe_str error ,'
'val:{0}'.format(val))
class ArgsTypeConsts(object):
STR = 'str'
INT = 'int'
FLOAT = 'float'
OBJ = 'object'
ARRAY = 'array'
class ArgsResolver(object):
def __init__(self, input_obj, obj_desc):
'''
:param input_obj: 输入需要校验的对象
:param obj_desc: 校验描述对象
'''
self.not_null(input_obj, 'input_obj').not_null(obj_desc,
'obj_desc')
self.input_obj = input_obj
self.obj_desc = obj_desc
def resolve(self):
return self.resolve_obj(self.input_obj, self.obj_desc)
def resolve_obj(self, ipt_obj, obj_desc):
if not obj_desc:
return ipt_obj
opt_obj = {}
for arg_desc in obj_desc:
name = arg_desc['name']
val = ipt_obj.get(name)
val = self.resolve_obj_entry(val, arg_desc)
opt_obj[name] = val
return opt_obj
def not_null(self, val, name='param'):
if val is None:
raise ValidateException(Code.invalid_params, '{0} can not be ' \
'null'.format(name))
return self
def ensure_arr(self, val, name='param'):
if not isinstance(val, (list, set)):
raise ValidateException(Code.invalid_params,
'{0} should be array:{1}'.format(
name, val))
def ensure_obj(self, val, name='param'):
if not isinstance(val, dict):
raise ValidateException(Code.invalid_params, '{0} should be '
'object:{1}'.format(
name, val))
def resolve_obj_entry(self, key_val, arg_desc):
name = arg_desc['name']
_type = arg_desc['type']
default_val = arg_desc.get('default', None)
def_required = 'default' not in arg_desc
required = arg_desc.get('required', def_required)
# 1.检查 是否必须
if required:
self.not_null(key_val, name)
# 2.检查是否需要设值默认值
if not required and key_val is None and default_val is not None:
# 非必须 key_val 为空 配置了 default_val
key_val = default_val
# 3. 检查类型
if key_val is not None:
if _type == ArgsTypeConsts.STR:
key_val = safe_str(key_val)
elif _type == ArgsTypeConsts.INT:
key_val = safe_int(key_val)
elif _type == ArgsTypeConsts.FLOAT:
key_val = safe_float(key_val)
elif _type == ArgsTypeConsts.OBJ:
# 确保是对象
self.ensure_obj(key_val, name)
object_desc = arg_desc.get('object_desc', None)
key_val = self.resolve_obj(key_val, object_desc)
elif _type == ArgsTypeConsts.ARRAY:
# 确保是数组
self.ensure_arr(key_val, name)
array_desc = arg_desc.get('array_desc')
key_val = self.resolve_arr(key_val, array_desc)
else:
raise ValidateException(Code.invalid_params,
'unknow type:{0}'.format(
_type))
return key_val
def resolve_arr(self, ipt_arr, arr_desc):
if not arr_desc:
return ipt_arr
opt_arr = []
_type = arr_desc.get('type')
for key_val in ipt_arr:
if _type == ArgsTypeConsts.STR:
key_val = safe_str(key_val)
opt_arr.append(key_val)
elif _type == ArgsTypeConsts.INT:
key_val = safe_int(key_val)
opt_arr.append(key_val)
elif _type == ArgsTypeConsts.FLOAT:
key_val = safe_float(key_val)
opt_arr.append(key_val)
elif _type == ArgsTypeConsts.OBJ:
# 确保是对象
self.ensure_obj(key_val)
object_desc = arr_desc.get('object_desc', None)
key_val = self.resolve_obj(key_val, object_desc)
opt_arr.append(key_val)
elif _type == ArgsTypeConsts.ARRAY:
# 确保是数组
self.ensure_arr(key_val)
array_desc = arr_desc.get('array_desc', None)
key_val = self.resolve_arr(key_val, array_desc)
opt_arr.append(key_val)
else:
raise ValidateException(Code.invalid_params, 'unknow type:{' \
'0}'.format(type))
return opt_arr
if __name__ == '__main__':
desc = [
# {'name': 'x', 'type': 'float', 'required': True, },
{'name': 'y', 'type': 'object', 'required': True,
'object_desc': [
{'name': 'a', 'type': 'int', 'required': True},
{'name': 'b', 'type': 'array', 'required': True,
'array_desc': {
'type': 'str'
}},
{'name': 'c', 'type': 'array', 'required': True,
'array_desc': {
'type': 'object',
'object_desc': [
{'name': 'a', 'type': 'int', 'required': True},
]
}}
]},
]
data = {
"x": "3.12",
"y": {
'a': '1',
'b': ['1', 2],
'c': [{'a': '1'}]
}
}
resolver = ArgsResolver(data, desc)
api_resp = None
try:
resolved_data = resolver.resolve()
api_resp = Code.api_resp(resp=resolved_data)
except ValidateException as v:
api_resp = Code.api_resp(v.result, v.reason)
print 'api_resp===\n', api_resp