github.com/renjunqing/…javascript
被校驗的數據以下:java
var data = {
a: 1
}
複製代碼
校驗規則a是一個大於0且小於20的整數
,則校驗描述以下:git
var rule = {
a: {
$type: 'Number',
$gt: 0, // 大於0
$lt: 20, // 小於20
$factor: 1, // 是1的整數倍
$message: 'a是一個大於0且小於20的整數' // 校驗不經過後的報錯提示
}
}
複製代碼
則校驗代碼以下:github
import Validator from 'data-police'
const ruleValidator = new Validator(rule)
ruleValidator.check(data).then(d => {
console.log(d)
}).catch(eMsg => {
console.log(eMsg)
})
複製代碼
npm install data-police --save
複製代碼
ES6
源碼,業務項目須要根據本身的環境進行編譯。TypeScript
的支持,內含.d.ts
聲明文件,使用者無需重複編寫。data-police 在語法設計上參考了mongodb的查詢語法,恰巧與 JSON Schema又有幾分神似。mongodb
描述符
。分兩種狀況npm
描述對象
。描述符都是對象的key,且以$
開頭json
$and
: 須要知足全部規則,如$and: [4, 5, 6]
表示這個節點的值要同時等於 4/5/6(☠️,顯然不可能,僅爲了介紹)。後端
$or
: 須要知足全部規則,如$or: [4, 5, 6]
表示這個節點的值等於4或等於5或等於6。數組
$if
: 知足條件才作此項校驗,如$if: [2, 3]
表示若是這個節點值等於2,則校驗它是否等於3(☠️,能感受到你要崩潰)。bash
邏輯運算優先級:「向上結合,深度優先」是基本原則。舉例說明:
{
$gt: {
$or: [
{
$or: [3, 4]
},
5
]
}
}
複製代碼
如上代碼示例:規則表述應是,(大於3或大於4)或大於5
,而非大於((3或4)或5)
。
交換等價性,在「向上結合,深度優先」的基本原則下,如下兩個規則rule1
和rule2
描述是等價的,從代碼複雜程度上看,rule1
更簡單些 。
const rule1 = {
$gt: {
$or: [3, 5]
}
}
const rule2 = {
$or: [
{
$gt: 3,
},
{
$gt: 5
}
]
}
複製代碼
$type
: 校驗數據類型,使用Object.prototype.toString.call(data).slice(8, -1)
獲得的類型值。
$value
: 值等於。
$fn
: 自定義函數。
$gt
: 小於。$gt: 4
,校驗值是否小於4。
$gte
: 小於等於。
$lt
: 大於。
$lte
: 大於等於。
$factor
: 因數,能夠是任意數字。$factor: 0.1
表示該值是不是0.1的整數倍,可用於校驗保留有效位數
。
$isEmail
: true/false。
$isTel
: true/false。
$isUrl
: true/false。
$isID
: true/false,身份證號。
$pattern
: 正則校驗字符串。
$len
: 字符串/數組的長度。
$message
: 用戶校驗未經過後的提示語。
$unique
: 數組元素惟一校驗標誌,用戶數組的每一個元素都是用同樣的校驗規則。
$proxy
: 代理子節點,用於指定路徑校驗模式下,由上層節點代理後端節點報錯(暫未實現)。
data-police容許用戶根據本身的業務特色添加自定義的描述符,Validator
類提供了3個靜態方法用來添加以上3種類型的描述符,分別是 loadCheckOperators
、loadLogicOperators
、loadHelpOperators
。使用姿式以下:
import Validator from 'data-police'
Validator.loadCheckOperators({
$isUpper(rule, dataValue) {
return /^\W+$/.test(dataValue)
},
// 與系統描述符重名,將會覆蓋系統描述符。同時,自定義描述符也能夠覆蓋,後來居上。
$gt(rule, dataValue) {
return dataValue < rule
}
})
複製代碼
描述符解析器是一個函數,入參如示例中所示,第一個是規則值,第二個是被校驗數據值。 在自定義描述符的命名規則上,建議以$
開頭,與系統描述符保持一致,但並不會作強制要求。 調用時機,loadxxxxOperators
方法能夠重複屢次調用,但針對某一描述符,必須在含有該描述符的規則實例化以前調用,不然會認爲這只是一個普通key,而非描述符。
對於結構層級比較深的數據,提供使用路徑的方式直達葉子節點,舉例:
// 數據
{
a: {
a: {
a: {
a: 1
}
}
}
}
// 正常規則,爲了一個葉子節點,嵌套的使人髮指
{
a: {
a: {
a: {
a: 1 // 相等性校驗,是否等於1
}
}
}
}
// 規則捷徑
{
'.a.a.a.a': 1 // 捷徑key以.開頭,做爲捷徑的標誌,因此要求被校驗的數據中key不能夠以.開頭
}
複製代碼
舉個表單數據校驗的場景,表單通常後多個字段,既要能校驗指定字段(填寫中),又要可以校驗整個表單(提交前),後者無需多言,針對前者提供了指定路徑校驗的方式。被校驗的數據支持兩種狀況,舉例以下:
const rule = {
a: 1,
b: 2
}
const data = {
a: 1,
b: 2
}
// 數據與規則是對應的結構,校驗過程是,根據路徑找到對應的規則和對應的數據值進行比對。
validator.check(data, '.a', 'root')
複製代碼
const rule = {
a: 1,
b: 2
}
const data = 1
// 數據便是在這個路徑下的值,校驗過程是,根據路徑找到規則,與傳入的值直接比對。
validator.check(data, '.a', 'branch')
複製代碼
規則校驗符不只能夠用來校驗「被校驗的數據」,並且能夠校驗「校驗規則」。舉例以下:
const rule = {
$len: {
$gt: 4
}
}
複製代碼
含義是:字符串的長度小於4
,$gt
被用來校驗$len
了。
並非全部的校驗規則均可以被校驗符校驗的,但全部可能被校驗的規則均可以被校驗,這句話有點拗口。舉例說明:
// 含義,大於的數據類型是Number,這句話自己就讀不通,因此$gt不能夠被$type校驗
{
$gt: {
$type: 'Number'
}
}
// 含義,數據類型中要包含Num字符串,前文提到過數據類型中新增了一個特殊類型NumStr,那下邊這個規則便可表示,數字和數字字符串。固然,也有其餘表示方式。
{
$type: {
$pattern: /Num/
}
}
複製代碼
那麼,怎麼區分哪些校驗符能夠被校驗,哪些不能夠呢?除了可能被校驗的規則均可以被校驗這條感性原則外,還有一條理性原則:能夠得出固定值的校驗規則均可以被校驗,好比5
的數據類型是固定值,那麼$type
就能夠被校驗,而5
大於幾就沒有固定值,能夠大於3能夠大於2等等,$gt
不能被校驗。在感性原則與理性原則相沖突的狀況下,都不會獲得指望的校驗結果。
約束模式指的是,規則與被校驗數據之間的字段對應關係,即數據是否能夠比規則多或者少字段,舉例以下:
const rule = {
a: 1,
b: 1
}
// 數據比規則少字段
const data1 = {
a: 1
}
// 數據比規則多字段
const data2 = {
a: 1,
b: 1,
c: 1
}
複製代碼
默認狀況下,多或少字段,都會被忽略,即只校驗相互匹配的字段,而經過校驗。若是你的業務場景對這方面有特殊要求,能夠經過傳入check
方法的第二個參數來設置。more: false
會報錯非法字段路徑
,less: false
會根據規則設置的$message
信息報錯。
rule.check(data, {
more: false,
less: false
})
複製代碼
單元測試覆蓋率90%
左右,基本覆蓋了全部狀況。
我對結構化校驗規則的見解:先說優勢,結構化更清晰,這表如今編寫時的思路和閱讀時的理解難度。缺點:受限於結構,有些極端邏輯編寫並不方便且代碼會累贅。