JSON schema與表單驗證
前言
每年最難過的時間就是現在這個時候了。今日早讀文章由美團金融前端團隊@神機運算元分享。
正文從這開始~
表單驗證是一個前端常聊的問題,在這個問題上實際上已經有很多種方案了,大體來說有以下兩種:
自己定義驗證原語,進行簡單封裝,按需定製。這個方案好在對於簡單的小表單上手快,幾經提煉可以形成自己的驗證庫,也可以代碼保持的精簡。但是出現跨項目復用的時候,容易出現需要補充大量新場景的情況,而且穩定性也不容易保證。
使用市面上已有的表單驗證庫。這個方案能秒殺大部分場景,但可定製性往往比較差,有些驗證庫方案甚至是基於某種組件庫的。另一方面,一旦開始使用某種驗證庫,未來想要切換就非常棘手。
那麼這裡說的方案是否能超越這兩種方案呢?這要從JSON Schema本身是什麼說起。
JSON Schema是一種用JSON數據來描述需要驗證的JSON的格式。利用這種格式,可以做到:
有據可依。每一種驗證方式都有固定的寫法,即使某一天跨語言,也只需很小的遷移成本。
包羅萬象。JSON Schema是一個在不斷發展的標準,基本上你想要的驗證方法都在裡面囊括了。
文本為準。JSON本身只是一段文本,因此這種驗證方法無需特別的工具即可編寫,也很利於保存和分享。
ajv是JS實現的JSON Schema庫。目前來說,它的性能和標準實現覆蓋都比較好,具體可以看它項目主頁的自我宣傳。
在不使用任何驗證庫、驗證工具的情況下,要驗證表單需要逐個欄位進行讀取、判斷。表單欄位越多,代碼的複雜度就越高,而且如果多個表單存在一定的共性,如何復用表單驗證也是一個麻煩事。
比如:
單從可讀性來說,這段代碼非常易讀,因為它足夠直白、簡單,但如果所有的表單驗證都這樣做,非常容易出錯,也不便於維護。
ajv本身只是一個驗證工具,這個工具接受一個JSON Schema和你的目標數據,然後返回驗證結果。和其他很多驗證工具類似,ajv提供了默認的報錯文案,默認情況下是英文的。
不過這個無法滿足產品對錶單驗證的需求。理想的表單驗證實際上包含以下需求:
對於每個異常的欄位,都需要指出其錯誤
錯誤需要是產品自己所希望的文案,而不是某種庫的內置文案,更別說是英文或者代碼中的欄位名了
表單驗證需要是有序的。直覺上來說,表單驗證需要先報頁面上最頂端的欄位的問題。
對於第一點,ajv完善提供了錯誤信息。但對於第二點,ajv沒有提供比較好的方式來處理,因為它的報錯信息是非常程式化的,對於某一類錯誤,它的文案都是套路。
針對這一點,引入ajv-errors就比較合理了。ajv-errors需要開發在原有的schema中增加一個自定義欄位,這個欄位對每一種報錯都可以定製自己的報錯文案,大致如下:
圖中errorMessage欄位是ajv-errors需要的欄位。
這樣一來,報錯文案的可定製性就非常強了。
那順序如何保證呢?
一般來說,JSON Schema中如果要驗證一個Object的屬性,是沒有顯式順序的,這個就好像Object在遍歷時本身就沒有順序一樣。在界面上每個欄位的位置,對於JSON Schema來說是透明的,無關的。
幸好ajv的報錯是數組形式返回的。儘管數組的順序在文檔中沒有明確指出,但這個報錯的格式非常友好,它會表明自己是哪個欄位。根據這一點,開發只需對報錯數組進行一次排序即可,大致如下:
圖的頂端指定了欄位的順序,而尾端則使用這個順序進行了排序。
完美,產品所有的需求都搞定了。
但作為一個合格的前端工程師,我自己是不能就這樣收工的。實際上在引入了ajv和ajv-errors之後,前端的JS資源在minify之後膨脹了100KB左右,即使因為gzip能夠做到只增加數十KB,這個結果也是不太理想的——太大了。
針對這個情況,如果退一步作為任意項目來對待,那可能我比較想要的做法是將這兩個庫都進行非同步按需載入。這樣做的話,多出來的尺寸基本上不會對首次載入造成影響,而且也足夠靈活。
但是我們這個項目受限於現有發布系統,沒有辦法支持webpack的非同步按需載入。這怎麼搞?
我自己的想法是,將驗證挪到node當中去做,讓伺服器完成這個過程,並將結果返回。
方案是:node端當中內置若干schema,並對每個schema命名,新加一個介面;瀏覽器端將需要驗證的數據和schema的名字發送到node端,並取回驗證結果。
從某種角度來說,這也是一種按需載入。粗略來看,這個驗證在瀏覽器端可能會被惡意用戶跳過,但只要你提交數據的介面最終沒有完善的驗證,那其他任何地方所增加的驗證都是可以被繞過的,放在瀏覽器還是node,也就沒什麼區別了。
從長遠來看,這個驗證的過程也可以再追加到業務介面上,這樣就無法被繞過了。
最後回過頭來看,基於JSON Schema的表單驗證方案不僅能夠解決我們在表單驗證上的基本需求,同時也在穩定性、可擴展性等方面有一定優勢,適合於絕大部分表單驗證的場景。
關於本文
作者:@神機運算元,美團金融前端團隊成員。喜歡簡單,樂於變成,富有激情的前端開發者。
點擊展開全文
※4種使用webpack提升vue應用的方式
※前端處理大數據的無限可能
※redux-react實踐總結
※【第994期】字型大小與行高
※總是一知半解的Event Loop
TAG:前端早讀課 |
※JSONObject 轉換時出錯 InvocationTargetException
※JSON程序的stringify()
※應用Protocol Buffers替代JSON的五個理由
※json schema
※在Python中使用JSON
※JSON編程的parse() 方法
※Discuz API JSON 適用於IOS及Android移動端開發
※NetCore2.1 WebAPI 根據swagger.json自動生成客戶端代碼
※golang json.Marshal interface 踩坑
※JSON Web Token 入門教程
※藉助Jackson的JsonTypeInfo註解實現多態類的解析
※使用 Python 處理 JSON 格式的數據
※Spring MVC請求及返回JSON數據
※FastJson反序列化漏洞利用的三個細節-TemplatesImpl利用鏈
※JSON Web Token :在 Web 應用間安全地傳遞信息
※linux-shell命令處理json數據
※jackson完成json和對象/map/list互轉
※Swift 項目中涉及到 JSONDecoder,網路請求,泛型協議式編程的一些記錄和想法
※為Python選擇一個更快的JSON庫
※Json解析(jquery頁面)