Blame view

utils/validator.js 8.92 KB
huangyi authored
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/**
 * 接口参数校验
 *
 * Created by y.huang on 17/5/21.
 */

/**
 * 返回一个错误对象
 *
 * msg 提示语
 */
const _errJson = (message) => {
    return {
        code: '203',
        description: message,
        name: '数据错误',
        errKey: 'valid'
    };
};

/**
 * 数字校验方法、支持小数负数、支持字符串数字自动转换
 *
 * option object类型,包含校验条件,如下
 *   require 是否必须,boolean类型,默认false不必须
 *   empty 可以是空字符串, boolean类型,默认true可以
 *   isInteger 是否必须整数,boolean类型,默认false不必须
 *   equal 等于某个值,number类型
 *   equalArr 等于几个值中的一个,array类型,array元素为number类型,长度不限
 *   smaller 小于某个值,number类型
 *   bigger 大于某个值,number类型
 */
const _numberValid = (option) => {
    const value = option.value;

    // 设置默认值
huangyi authored
37 38 39
    option.require = option.require === void(0) ? false : option.require;
    option.integer = option.integer === void(0) ? false : option.integer;
    option.empty = option.empty === void(0) ? true : option.empty;
huangyi authored
40
huangyi authored
41
    if (value === void(0)) {
huangyi authored
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
        if (option.require === true) {
            throw _errJson(`${option.param} 参数是必须的`);
        } else {
            return value;
        }

    }

    if (typeof value === 'boolean' || typeof value === 'object') {
        throw _errJson(`${option.param} 参数类型必须是数字或字符串数字`);
    }

    if (value === '') {
        if (option.empty === false) {
            throw _errJson(`${option.param}  参数不能为空字符串`);
        } else {
huangyi authored
58
            return void(0);
huangyi authored
59 60 61 62 63 64
        }
    }

    const numValue = Number(value);

    if (!Number.isNaN(numValue) && Math.abs(numValue) !== Infinity) {
huangyi authored
65
        if (option.equal !== void(0)) {
huangyi authored
66 67 68 69 70
            if (numValue !== option.equal) {
                throw _errJson(`${option.param} 参数必须等于 ${option.equal}`);
            }
            return numValue;
        }
huangyi authored
71
        if (option.equalArr !== void(0)) {
huangyi authored
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
            let result = false;

            for (let item of option.equalArr) {
                if (item === numValue) {
                    result = true;
                    break;
                }
            }

            if (!result) {
                throw _errJson(`${option.param} 参数必须等于 ${option.equalArr} 中的某个`);
            }
            return numValue;
        }

        if (option.integer === true) {
            if (!Number.isInteger(numValue)) {
                throw _errJson(`${option.param} 参数必须是整数`);
            }
        }
huangyi authored
92
        if (option.smaller !== void(0)) {
huangyi authored
93 94 95 96
            if (!numValue < option.smaller) {
                throw _errJson(`${option.param} 参数必须小于 ${option.smaller}`);
            }
        }
huangyi authored
97
        if (option.bigger !== void(0)) {
huangyi authored
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
            if (!numValue > option.bigger) {
                throw _errJson(`${option.param} 参数必须大于 ${option.bigger}`);
            }
        }

        return numValue;
    } else {
        throw _errJson(`${option.param} 参数类型必须是数字或字符串数字`);
    }
};

/**
 * 字符串校验方法、支持数字自动转换
 *
 * option object类型,包含校验条件,如下
 *   require 是否必须,boolean类型,默认false不必须
 *   empty 是否可以为空字符串,boolean类型,默认true可以
 *   emptyFilter 过滤空字符串,boolean类型,true为需要过滤,  使用时empty必须为true
 *   regex 正则匹配,其值应该是'phone,email'中的一个,或是一个自定义的正则对象或正则自面量
 *   start 字符串长度大于,number类型
 *   end 字符串长度小于,number类型
 */
const _stringValid = (option) => {
    const value = option.value;

    // 设置默认值
    option.require = option.require || false;
    option.empty = option.empty || true;
huangyi authored
127
    if (value === void(0)) {
huangyi authored
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        if (option.require === true) {
            throw _errJson(`${option.param} 参数是必须的`);
        } else {
            return value;
        }
    }

    if (Number.isNaN(value) || Math.abs(value) === Infinity ||
        typeof value === 'boolean' || typeof value === 'object') {
        throw _errJson(`${option.param} 参数类型必须是数字或字符串`);
    }

    const strValue = String(value).trim();

    if (strValue === '') {
        if (option.empty === false) {
            throw _errJson(`${option.param} 参数不能为空`);
        } else {
            if (option.emptyFilter === true) {
huangyi authored
147
                return void(0);
huangyi authored
148 149 150 151
            }
            return strValue;
        }
    }
huangyi authored
152
    if (option.regex !== void(0)) {
huangyi authored
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
        switch (option.regex) {
            case 'phone':
                if (!/^1[0-9]{10}$/.test(strValue)) {
                    throw _errJson(`${option.param} 参数不符合手机格式`);
                }
                break;
            case 'email':
                if (!/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(strValue)) {
                    throw _errJson(`${option.param} 参数不符合邮箱格式`);
                }
                break;
            default:
                if (!option.regex.test(strValue)) {
                    throw _errJson(`${option.param} 参数不符合自定义格式`);
                }
        }
        return strValue;
    }
huangyi authored
171
    if (option.end !== void(0)) {
huangyi authored
172 173 174 175
        if (!strValue.length < option.end) {
            throw _errJson(`${option.param} 参数长度必须小于 ${option.end}`);
        }
    }
huangyi authored
176
    if (option.start !== void(0)) {
huangyi authored
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
        if (!strValue.length > option.start) {
            throw _errJson(`${option.param} 参数长度必须大于 ${option.start}`);
        }
    }
    return strValue;
};

/**
 * 布尔校验方法、支持字符串布尔类型自动转换
 *
 * option object类型,包含校验条件,如下
 *   require 是否必须,boolean类型,默认false不必需
 *   empty 是否可以为空字符串,boolean类型,默认true可以
 *   emptyFilter 过滤空字符串,boolean类型,true为需要过滤,  使用时empty必须为true
 */
const _booleanValid = (option) => {
    const value = option.value;

    // 设置默认值

    option.require = option.require || false;
    option.empty = option.empty || true;
huangyi authored
200
    if (value === void(0)) {
huangyi authored
201 202 203 204 205 206 207 208 209 210 211 212
        if (option.require === true) {
            throw _errJson(`${option.param} 参数是必须的`);
        } else {
            return value;
        }
    }

    if (value === '') {
        if (option.empty === false) {
            throw _errJson(`${option.param} 参数不能为空`);
        } else {
            if (option.emptyFilter === true) {
huangyi authored
213
                return void(0);
huangyi authored
214 215 216 217 218 219 220 221 222 223 224
            }
            return value;
        }
    } else {
        if (typeof value !== 'boolean' && value !== 'true' && value !== 'false') {
            throw _errJson(`${option.param} 参数类型必须为boolean`);
        }
        return Boolean(value);
    }
};
huangyi authored
225 226 227 228 229 230 231
const _objectValid = (option) => {
    const value = option.value;

    // 设置默认值
    option.require = option.require || false;
    option.empty = option.empty || true;
huangyi authored
232
    if (value === void(0) || value === null) {
huangyi authored
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
        if (option.require === true) {
            throw _errJson(`${option.param} 参数是必须的`);
        } else {
            return null;
        }
    }
    if (typeof value === 'object') {
        let valueArr = Object.keys(value);

        if (!valueArr.length) {
            if (option.empty === false) {
                throw _errJson(`${option.param} 参数不能为空`);
            } else {
                return null;
            }
        } else {
            return value;
        }
    } else {
        throw _errJson(`${option.param} 参数格式错误`);
    }
};
huangyi authored
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
/*
 * data: 需要校验的数据对象
 * option: 校验规则对象,eg: {'name', {type: 'string', require: true}}
 *
 */
const valid = (data, option) => {
    Object.keys(option).forEach(item => {
        let opt = option[item];

        opt.value = data[item];
        opt.param = item;

        switch (opt.type) {
            case 'number':
                data[item] = _numberValid(opt);
huangyi authored
271
                if (data[item] === void(0)) {
huangyi authored
272 273 274 275 276
                    delete data[item];
                }
                break;
            case 'string':
                data[item] = _stringValid(opt);
huangyi authored
277
                if (data[item] === void(0)) {
huangyi authored
278 279 280 281 282
                    delete data[item];
                }
                break;
            case 'boolean':
                data[item] = _booleanValid(opt);
huangyi authored
283
                if (data[item] === void(0)) {
huangyi authored
284 285 286
                    delete data[item];
                }
                break;
huangyi authored
287 288
            case 'object':
                data[item] = _objectValid(opt);
huangyi authored
289
                if (data[item] === void(0)) {
huangyi authored
290 291 292
                    delete data[item];
                }
                break;
huangyi authored
293 294
            default:
                break;
huangyi authored
295 296 297 298 299 300 301
        }
    });

    return data;
};

module.exports = valid;