protovalidate
是一系列程式庫,旨在根據使用者定義的驗證規則在執行時驗證 Protobuf 訊息。它由 Google 的通用表達式語言 (CEL) 提供支持,為定義和評估自訂驗證規則提供了靈活且高效的基礎。 protovalidate
的主要目標是幫助開發人員確保整個網路中資料的一致性和完整性,而無需產生程式碼。
筆記
protovalidate
是 protoc-gen-validate 的精神繼承者。它不需要生成任何程式碼並支援自訂約束。
我們建議新專案和現有專案過渡到使用protovalidate
而不是protoc-gen-validate
。
如果您想了解更多有關protoc-gen-validate
的局限性以及我們如何設計得更好的protovalidate
信息,請閱讀我們的部落格文章。
該存儲庫是protovalidate
專案的核心。它包含:
protovalidate
protoc-gen-validate
增量遷移protovalidate
的範例.proto
文件protovalidate
實作的驗收測試protovalidate
的運行時實作可以在它們自己的儲存庫中找到:
protovalidate-go
(測試版)protovalidate-cc
(測試版)protovalidate-java
(測試版)protovalidate-python
(測試版)protovalidate-ts
(即將推出)有興趣添加另一種語言的支援嗎?查看我們的貢獻指南。
若要在 Protobuf 訊息中定義約束,請將buf/validate/validate.proto
匯入至.proto
檔案:
syntax = "proto3" ;
package my.package ;
import "buf/validate/validate.proto" ;
buf
構建將buf.build/bufbuild/protovalidate
的依賴項加入模組的buf.yaml
:
version : v1
# <snip>
deps :
- buf.build/bufbuild/protovalidate
# <snip>
修改buf.yaml
後,不要忘記執行buf mod update
以確保您的依賴項是最新的。
protoc
構建將指向proto/protovalidate
目錄內容的導入路徑( -I
標誌)加入到protoc
的呼叫中:
protoc
-I ./vendor/protovalidate/proto/protovalidate
# <snip>
可以使用buf.validate
Protobuf 套件強制執行驗證約束。規則直接在.proto
文件中指定。
讓我們考慮幾個例子:
標量欄位驗證:對於基本的User
訊息,我們可以強制執行約束,例如使用者名稱的最小長度。
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message User {
// User's name, must be at least 1 character long.
string name = 1 [ (buf.validate .field ) .string .min_len = 1 ];
}
地圖欄位驗證:對於具有商品數量地圖的Product
訊息,我們可以確保所有數量均為正數。
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message Product {
// Map of item quantities, all quantities must be positive.
map < string , int32 > item_quantities = 1 [ (buf.validate .field ) .map.values.int32 .gt = 0 ];
}
眾所周知的類型(WKT)驗證:對於User
訊息,我們可以添加一個約束來確保created_at
時間戳是過去的。
syntax = "proto3" ;
import "google/protobuf/timestamp.proto" ;
import "buf/validate/validate.proto" ;
message User {
// User's creation date must be in the past.
google.protobuf.Timestamp created_at = 1 [ (buf.validate .field ) .timestamp .lt_now = true ];
}
對於更高級或自訂約束, protovalidate
允許使用可以跨欄位合併資訊的 CEL 表達式。
字段級表達式:我們可以強制以字串形式發送的產品price
包含貨幣符號,例如“$”或“£”。我們要確保價格為正且貨幣符號有效。
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message Product {
string price = 1 [ (buf.validate .field ).cel = {
id : "product.price" ,
message : "Price must be positive and include a valid currency symbol ($ or £)" ,
expression : "(this.startsWith('$') || this.startsWith('£')) && double(this.substring(1)) > 0"
}];
}
訊息級表達式:對於Transaction
訊息,我們可以使用訊息級CEL表達式來確保delivery_date
始終在purchase_date
之後。
syntax = "proto3" ;
import "google/protobuf/timestamp.proto" ;
import "buf/validate/validate.proto" ;
message Transaction {
google.protobuf.Timestamp purchase_date = 1 ;
google.protobuf.Timestamp delivery_date = 2 ;
option (buf.validate .message ).cel = {
id : "transaction.delivery_date" ,
message : "Delivery date must be after purchase date" ,
expression : "this.delivery_date > this.purchase_date"
};
}
在表達式中產生錯誤訊息:我們可以直接在 CEL 表達式中產生自訂錯誤訊息。在此範例中,如果age
小於 18,則 CEL 表達式的計算結果將是錯誤訊息字串。
syntax = "proto3" ;
import "buf/validate/validate.proto" ;
message User {
int32 age = 1 [ (buf.validate .field ).cel = {
id : "user.age" ,
expression : "this < 18 ? 'User must be at least 18 years old': ''"
}];
}
查看有關標準約束和自訂 CEL 約束的examples
。
使用約束註釋訊息後,使用受支援的語言庫之一進行驗證;不需要額外的程式碼產生。
protovalidate
提供了一個強大的框架,透過對各種資料類型實施標準和自訂約束來驗證 Protobuf 訊息,並在發生驗證違規時提供詳細的錯誤資訊。有關其所有組件、支援的約束以及如何有效使用它們的詳細概述,請參閱我們的綜合文件。關鍵組件包括:
標準約束: protovalidate
支援所有欄位類型的廣泛標準約束以及 Protobuf 眾所周知類型的特殊功能。您可以將這些約束套用至 Protobuf 訊息,以確保它們符合某些常見條件。
自訂約束:借助 Google 的通用表達式語言 (CEL), protovalidate
可讓您建立複雜的自訂約束,以處理欄位和訊息層級的標準約束未涵蓋的獨特驗證場景。
錯誤處理:發生違規時, protovalidate
會提供詳細的錯誤訊息,幫助您快速識別問題根源並修復問題。
protovalidate
是protoc-gen-validate
的精神繼承者,提供原始插件中存在的所有相同功能,無需自訂程式碼生成,以及在 CEL 中描述複雜約束的新能力。
protovalidate
的約束非常接近地模擬protoc-gen-validate
中的約束,以確保開發人員輕鬆過渡。若要從protoc-gen-validate
遷移到protovalidate
,請使用提供的遷移工具逐步升級您的.proto
檔案。
根據 Apache 2 許可證提供。