Validus 4.1.4
dotnet add package Validus --version 4.1.4
NuGet\Install-Package Validus -Version 4.1.4
<PackageReference Include="Validus" Version="4.1.4" />
paket add Validus --version 4.1.4
#r "nuget: Validus, 4.1.4"
// Install Validus as a Cake Addin #addin nuget:?package=Validus&version=4.1.4 // Install Validus as a Cake Tool #tool nuget:?package=Validus&version=4.1.4
Validus
Validus 是一个可扩展的 F# 验证库,具有大多数原始类型和内置验证器,可以通过自定义验证器轻松扩展。
主要特性
- 组合验证。
- 内置 对大多数原始类型的验证器。
- 通过 自定义-验证器 简单扩展。
- 通过
Validus.Operators
提供干净组合语法的后缀 操作符。 - 应用计算表达式.
- 非常适合创建 值对象(即,受限的原始类型)。
快速入门
从不受信任的源获取输入的常见示例 PersonDto
(例如,HTML 表单提交),应用验证并根据成功/失败产生结果。
open System
open System.Net.Mail
open Validus
type PersonDto =
{ FirstName : string
LastName : string
Email : string
Age : int option
StartDate : DateTime option }
type Name =
{ First : string
Last : string }
type Person =
{ Name : Name
Email : string
Age : int option
StartDate : DateTime }
module Person =
let ofDto (dto : PersonDto) =
// A basic validator
let nameValidator =
Check.String.betweenLen 3 64
// A custom email validator, using the *built-in* functionality
// from System.Net.Mail
let emailValidator =
let msg = sprintf "Please provide a valid %s"
let rule v =
let success, _ = MailAddress.TryCreate v
success
Validator.create msg rule
// Composing multiple validators to form complex validation rules,
// overriding default error message (Note: "Check.WithMessage.String" as
// opposed to "Check.String")
let emailValidator =
let emailPatternValidator =
let msg = sprintf "Please provide a valid %s"
Check.WithMessage.String.pattern @"[^@]+@[^\.]+\..+" msg
ValidatorGroup(Check.String.betweenLen 8 512)
.And(emailPatternValidator)
.Build()
// Defining a validator for an option value
let ageValidator =
Check.optional (Check.Int.between 1 100)
// Defining a validator for an option value that is required
let dateValidator =
Check.required (Check.DateTime.greaterThan DateTime.Now)
validate {
let! first = nameValidator "First name" dto.FirstName
and! last = nameValidator "Last name" dto.LastName
and! email = emailValidator "Email address" dto.Email
and! age = ageValidator "Age" dto.Age
and! startDate = dateValidator "Start Date" dto.StartDate
// Construct Person if all validators return Success
return {
Name = { First = first; Last = last }
Email = email
Age = age
StartDate = startDate }
}
注意:此示例仅用于演示,不建议使用正则表达式尝试验证电子邮件。请使用 System.Net.MailAddress。
使用验证器
let dto : PersonDto =
{ FirstName = "John"
LastName = "Doe"
Email = "john.doe@url.com"
Age = Some 63
StartDate = Some (new DateTime(2058, 1, 1)) }
match validatePersonDto dto with
| Ok p -> printfn "%A" p
| Error e ->
e
|> ValidationErrors.toList
|> Seq.iter (printfn "%s")
验证复杂类型
Validus 包含一个 应用计算表达式,在本例中允许在执行验证器时累积验证错误。
open Validus
type PersonDto =
{ FirstName : string
LastName : string
Age : int option }
type Name =
{ First : string
Last : string }
type Person =
{ Name : Name
Age : int option }
module Person =
let ofDto (dto : PersonDto) =
let nameValidator = Check.String.betweenLen 3 64
let firstNameValidator =
ValidatorGroup(nameValidator)
.Then(Check.String.notEquals dto.LastName)
.Build()
validate {
let! first = firstNameValidator "First name" dto.FirstName
and! last = nameValidator "Last name" dto.LastName
and! age = Check.optional (Check.Int.between 1 120) "Age" dto.Age
return {
Name = { First = first; Last = last }
Age = age }
}
创建自定义验证器
open System.Net.Mail
open Validus
let fooValidator =
let fooRule v = v = "foo"
let fooMessage = sprintf "%s must be a string that matches 'foo'"
Validator.create fooMessage fooRule
"bar"
|> fooValidator "Test string"
合并验证器
通过结合使用 ValidatorGroup
API 将验证器组合在一起,可以创建复杂的验证链和水闸。对于那些喜欢这种语法风格的人来说,一整套操作符也都可以使用。
open System.Net.Mail
open Validus
let emailPatternValidator =
let msg = sprintf "The %s input is not formatted as expected"
Check.WithMessage.String.pattern @"[^@]+@[^\.]+\..+" msg
// A custom validator that uses System.Net.Mail to validate email
let mailAddressValidator =
let msg = sprintf "The %s input is not a valid email address"
let rule (x : string) =
let success, _ = MailAddress.TryCreate x
success
Validator.create msg rule
let emailValidator =
ValidatorGroup(Check.String.betweenLen 8 512)
.And(emailPatternValidator)
.Then(mailAddressValidator) // only executes when prior two steps are `Ok`
.Build()
"fake@test"
|> emailValidator "Login email"
我们可以使用任何验证器或验证器的任意组合来验证集合
let emails = [ "fake@test"; "bob@fsharp.org"; "x" ]
let result =
emails
|> List.map (emailValidator "Login email")
值对象
一般来说,创建值对象是一个好主意,有时也被称为 值类型 或 约束原语,以表示比通常用于表示它们的原始类型更具体的单个数据点。
示例 1:电子邮件地址值对象
一个很好的例子是将电子邮件地址表示为一个 string
文字,因为它存在于许多程序中。然而,这种方法是有缺陷的,因为电子邮件地址的域比字符串允许的范围更窄。例如,""
或 null
不是有效的电子邮件地址。
为了解决这个问题,我们可以创建一个包装类型来表示电子邮件地址,它隐藏实现细节并提供了生成类型的智能构造。
open System.Net.Mail
type Email =
private { Email : string }
override x.ToString () = x.Email
// Note the transformation from string -> Email
static member Of : Validator<string, Email> = fun field input ->
let rule (x : string) =
if x = "" then false
else
try
let addr = MailAddress(x)
if addr.Address = x then true
else false
with
| :? FormatException -> false
let message = sprintf "%s must be a valid email address"
input
|> Validator.create message rule field
|> Result.map (fun v -> { Email = v })
示例 2:E164 格式化电话号码
type E164 =
private { E164 : string }
override x.ToString() = x.E164
static member Of : Validator<string, E164> = fun field input ->
let e164Regex = @"^\+[1-9]\d{1,14}$"
let message = sprintf "%s must be a valid E164 telephone number"
input
|> Check.WithMessage.String.pattern e164Regex message field
|> Result.map (fun v -> { E164 = v })
内置验证器
注意:预设了英文语言默认错误消息的验证器位于
Check
模块中。
equals
适用范围:string, int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string equals
// "foo" displaying the standard error message.
let equalsFoo =
Check.String.equals "foo" "fieldName"
equalsFoo "bar"
// Define a validator which checks if a string equals
// "foo" displaying a custom error message (string -> string).
let equalsFooCustom =
let msg = sprintf "%s must equal the word 'foo'"
Check.WithMessage.String.equals "foo" msg "fieldName"
equalsFooCustom "bar"
notEquals
适用范围:string, int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is not
// equal to "foo" displaying the standard error message.
let notEqualsFoo =
Check.String.notEquals "foo" "fieldName"
notEqualsFoo "bar"
// Define a validator which checks if a string is not
// equal to "foo" displaying a custom error message (string -> string)
let notEqualsFooCustom =
let msg = sprintf "%s must not equal the word 'foo'"
Check.WithMessage.String.notEquals "foo" msg "fieldName"
notEqualsFooCustom "bar"
between
适用范围:int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan
open Validus
// Define a validator which checks if an int is between
// 1 and 100 (inclusive) displaying the standard error message.
let between1and100 =
Check.Int.between 1 100 "fieldName"
between1and100 12 // Result<int, ValidationErrors>
// Define a validator which checks if an int is between
// 1 and 100 (inclusive) displaying a custom error message.
let between1and100Custom =
let msg = sprintf "%s must be between 1 and 100"
Check.WithMessage.Int.between 1 100 msg "fieldName"
between1and100Custom 12 // Result<int, ValidationErrors>
greaterThan
适用范围:int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan
open Validus
// Define a validator which checks if an int is greater than
// 100 displaying the standard error message.
let greaterThan100 =
Check.Int.greaterThan 100 "fieldName"
greaterThan100 12 // Result<int, ValidationErrors>
// Define a validator which checks if an int is greater than
// 100 displaying a custom error message.
let greaterThan100Custom =
let msg = sprintf "%s must be greater than 100"
Check.WithMessage.Int.greaterThan 100 msg "fieldName"
greaterThan100Custom 12 // Result<int, ValidationErrors>
greaterThanOrEqualTo
适用范围:int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan
open Validus
// Define a validator which checks if an int is greater than
// or equal to 100 displaying the standard error message.
let greaterThanOrEqualTo100 =
Check.Int.greaterThanOrEqualTo 100 "fieldName"
greaterThanOrEqualTo100 12 // Result<int, ValidationErrors>
// Define a validator which checks if an int is greater than
// or equal to 100 displaying a custom error message.
let greaterThanOrEqualTo100Custom =
let msg = sprintf "%s must be greater than or equal to 100"
Check.WithMessage.Int.greaterThanOrEqualTo 100 msg "fieldName"
greaterThanOrEqualTo100Custom 12 // Result<int, ValidationErrors>
lessThan
适用范围:int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan
open Validus
// Define a validator which checks if an int is less than
// 100 displaying the standard error message.
let lessThan100 =
Check.Int.lessThan 100 "fieldName"
lessThan100 12 // Result<int, ValidationErrors>
// Define a validator which checks if an int is less than
// 100 displaying a custom error message.
let lessThan100Custom =
let msg = sprintf "%s must be less than 100"
Check.WithMessage.Int.lessThan 100 msg "fieldName"
lessThan100Custom 12 // Result<int, ValidationErrors>
lessThanOrEqualTo
适用范围:int16, int, int64, decimal, float, DateTime, DateTimeOffset, TimeSpan
open Validus
// Define a validator which checks if an int is less than
// or equal to 100 displaying the standard error message.
let lessThanOrEqualTo100 =
Check.Int.lessThanOrEqualTo 100 "fieldName"
lessThanOrEqualTo100 12 // Result<int, ValidationErrors>
// Define a validator which checks if an int is less than
// or equal to 100 displaying a custom error message.
let lessThanOrEqualTo100Custom =
let msg = sprintf "%s must be less than or equal to 100"
Check.WithMessage.Int.lessThanOrEqualTo 100 msg "fieldName"
lessThanOrEqualTo100Custom 12 // Result<int, ValidationErrors>
betweenLen
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is between
// 1 and 100 chars displaying the standard error message.
let between1and100Chars =
Check.String.betweenLen 1 100 "fieldName"
between1and100Chars "validus"
// Define a validator which checks if a string is between
// 1 and 100 chars displaying a custom error message.
let between1and100CharsCustom =
let msg = sprintf "%s must be between 1 and 100 chars"
Check.WithMessage.String.betweenLen 1 100 msg "fieldName"
between1and100CharsCustom "validus"
equalsLen
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is equals to
// 100 chars displaying the standard error message.
let equals100Chars =
Check.String.equalsLen 100 "fieldName"
equals100Chars "validus"
// Define a validator which checks if a string is equals to
// 100 chars displaying a custom error message.
let equals100CharsCustom =
let msg = sprintf "%s must be 100 chars"
Check.WithMessage.String.equalsLen 100 msg "fieldName"
equals100CharsCustom "validus"
greaterThanLen
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is greater than
// 100 chars displaying the standard error message.
let greaterThan100Chars =
Check.String.greaterThanLen 100 "fieldName"
greaterThan100Chars "validus"
// Define a validator which checks if a string is greater than
// 100 chars displaying a custom error message.
let greaterThan100CharsCustom =
let msg = sprintf "%s must be greater than 100 chars"
Check.WithMessage.String.greaterThanLen 100 msg "fieldName"
greaterThan100CharsCustom "validus"
greaterThanOrEqualToLen
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is greater than
// or equal to 100 chars displaying the standard error message.
let greaterThanOrEqualTo100Chars =
Check.String.greaterThanOrEqualToLen 100 "fieldName"
greaterThanOrEqualTo100Chars "validus"
// Define a validator which checks if a string is greater than
// or equal to 100 chars displaying a custom error message.
let greaterThanOrEqualTo100CharsCustom =
let msg = sprintf "%s must be greater than or equal to 100 chars"
Check.WithMessage.String.greaterThanOrEqualToLen 100 msg "fieldName"
greaterThanOrEqualTo100CharsCustom "validus"
lessThanLen
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is less tha
// 100 chars displaying the standard error message.
let lessThan100Chars =
Check.String.lessThanLen 100 "fieldName"
lessThan100Chars "validus"
// Define a validator which checks if a string is less tha
// 100 chars displaying a custom error message.
let lessThan100CharsCustom =
let msg = sprintf "%s must be less than 100 chars"
Check.WithMessage.String.lessThanLen 100 msg "fieldName"
lessThan100CharsCustom "validus"
lessThanOrEqualToLen
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is less tha
// or equal to 100 chars displaying the standard error message.
let lessThanOrEqualTo100Chars =
Check.String.lessThanOrEqualToLen 100 "fieldName"
lessThanOrEqualTo100Chars "validus"
// Define a validator which checks if a string is less tha
// or equal to 100 chars displaying a custom error message.
let lessThanOrEqualTo100CharsCustom =
let msg = sprintf "%s must be less than 100 chars"
Check.WithMessage.String.lessThanOrEqualToLen 100 msg "fieldName"
lessThanOrEqualTo100CharsCustom "validus"
empty
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is empty
// displaying the standard error message.
let stringIsEmpty =
Check.String.empty "fieldName"
stringIsEmpty "validus"
// Define a validator which checks if a string is empty
// displaying a custom error message.
let stringIsEmptyCustom =
let msg = sprintf "%s must be empty"
Check.WithMessage.String.empty msg "fieldName"
stringIsEmptyCustom "validus"
notEmpty
适用范围:string, 'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a string is not empty
// displaying the standard error message.
let stringIsNotEmpty =
Check.String.notEmpty "fieldName"
stringIsNotEmpty "validus"
// Define a validator which checks if a string is not empty
// displaying a custom error message.
let stringIsNotEmptyCustom =
let msg = sprintf "%s must not be empty"
Check.WithMessage.String.notEmpty msg "fieldName"
stringIsNotEmptyCustom "validus"
pattern
适用范围:string
open Validus
// Define a validator which checks if a string matches the
// provided regex displaying the standard error message.
let stringIsChars =
Check.String.pattern "[a-z]+" "fieldName"
stringIsChars "validus"
// Define a validator which checks if a string matches the
// provided regex displaying a custom error message.
let stringIsCharsCustom =
let msg = sprintf "%s must follow the pattern [a-z]"
Check.WithMessage.String.pattern "[a-z]" msg "fieldName"
stringIsCharsCustom "validus"
exists
适用范围:'a array, 'a list, 'a seq
open Validus
// Define a validator which checks if a collection matches the provided predicate
// displaying the standard error message.
let collectionContains =
Check.List.exists (fun x -> x = 1) "fieldName"
collectionContains [1]
// Define a validator which checks if a string is not empty
// displaying a custom error message.
let collectionContainsCustom =
let msg = sprintf "%s must contain the value '1'"
Check.WithMessage.List.exists (fun x -> x = 1) msg "fieldName"
collectionContainsCustom [1]
自定义操作符
操作符 | 描述 |
---|---|
<+> |
组合两个相同类型的验证器 |
*\|* |
将验证器的 Ok 结果映射到,用于选择 <\|> 的高优先级。 |
*\| |
将验证器的 Ok 结果设置为固定值,用于选择 <\|> 的高优先级。 |
>>\| |
将验证器的 Ok 结果映射到,用于链式验证的低优先级 |
>\| |
将验证器的 Ok 结果设置为固定值,用于链式验证的低优先级 |
>>= |
将验证器的 Ok 结果与返回 Result 的单参数函数绑定 |
<<= |
将验证器的 Ok 结果与返回 Result 的单参数函数反绑定 |
>>% |
将验证器的 Ok 结果设置为固定的 Result 值 |
<\|> |
引入选择:如果右侧验证 Ok ,则选择该结果,否则继续下一个验证器 |
>=> |
组合两个验证器。除了组合 <+> 外,这可以改变结果类型。 |
<=< |
反向组合两个验证器(右侧先评估)。除了组合 <+> 外,这可以改变结果类型。 |
.>> |
组合两个验证器,但保留左侧的结果。忽略右侧的结果,除非它返回一个错误。 |
>>. |
组合两个验证器,但保留右侧的结果。忽略左侧的结果,除非它返回一个错误。 |
.>>. |
组合两个验证器,并保留两边的嵌套结果作为元组。 |
使用组合操作符重写上面的示例代码
open System.Net.Mail
open Validus
open Validus.Operators
let msg = sprintf "Please provide a valid %s"
let emailPatternValidator =
Check.WithMessage.String.pattern @"[^@]+@[^\.]+\..+" msg
// A custom validator that uses System.Net.Mail to validate email
let mailAddressValidator =
let rule (x : string) =
if x = "" then false
else
try
let addr = MailAddress(x)
if addr.Address = x then true
else false
with
| :? FormatException -> false
Validator.create msg rule
let emailValidator =
Check.String.betweenLen 8 512 // check string is between 8 and 512 chars
<+> emailPatternValidator // and, check string match email regex
>=> mailAddressValidator // then, check using System.Net.Mail if prior two steps are `Ok`
"fake@test"
|> emailValidator "Login email"
一个更复杂的例子,涉及到“链式”验证器和两者都涉及“选择”赋值和映射
open System
open Validus
open Validus.Operators
type AgeGroup =
| Adult of int
| Child
| Senior
let ageValidator =
Check.String.pattern @"\d+" *|* Int32.Parse // if pattern matches, convert to Int32
>=> Check.Int.between 0 120 // first check age between 0 and 120
>=> (Check.Int.between 0 17 *| Child // then, check age between 0 an 17 assigning Child
<|> Check.Int.greaterThan 65 *| Senior // or, check age greater than 65 assiging Senior
<|> Check.Int.between 18 65 *|* Adult) // or, check age between 18 and 65 assigning adult mapping converted input
发现错误了吗?
有一个问题与此相关。
许可证
由Pim Brouwers在多伦多创建,并使用♥。许可证遵循Pim Brouwers的Apache License 2.0。
产品 | 版本 兼容的以及额外的计算目标框架版本。 |
---|---|
.NET | net5.0 已计算。 net5.0-windows 已计算。 net6.0 已计算。 net6.0-android 已计算。 net6.0-ios 已计算。 net6.0-maccatalyst 已计算。 net6.0-macos 已计算。 net6.0-tvos 已计算。 net6.0-windows 已计算。 net7.0 已计算。 net7.0-android 已计算。 net7.0-ios 已计算。 net7.0-maccatalyst 已计算。 net7.0-macos 已计算。 net7.0-tvos 已计算。 net7.0-windows 已计算。 net8.0 已计算。 net8.0-android 已计算。 net8.0-browser 已计算。 net8.0-ios 已计算。 net8.0-maccatalyst 已计算。 net8.0-macos 已计算。 net8.0-tvos 已计算。 net8.0-windows 已计算。 |
.NET Core | netcoreapp2.0 已计算。 netcoreapp2.1 已计算。 netcoreapp2.2 已计算。 netcoreapp3.0 已计算。 netcoreapp3.1 已计算。 |
.NET Standard | netstandard2.0 兼容。 netstandard2.1 已计算。 |
.NET Framework | net461 已计算。 net462 已计算。 net463 已计算。 net47 已计算。 net471 已计算。 net472 已计算。 net48 已计算。 net481 已计算。 |
MonoAndroid | monoandroid 已计算。 |
MonoMac | monomac 已计算。 |
MonoTouch | monotouch 已计算。 |
Tizen | tizen40 已计算。 tizen60 已计算。 |
Xamarin.iOS | xamarinios 已计算。 |
Xamarin.Mac | xamarinmac 已计算。 |
Xamarin.TVOS | xamarintvos 已计算。 |
Xamarin.WatchOS | xamarinwatchos 已计算。 |
-
.NETStandard 2.0
- FSharp.Core (>= 4.5.2)
NuGet 包
此包不被任何 NuGet 包使用。
GitHub 仓库
此包不被任何流行的 GitHub 仓库使用。
版本 | 下载 | 最后更新 |
---|---|---|
4.1.4 | 1,168 | 3/15/2024 |
4.1.3 | 5,214 | 7/15/2023 |
4.1.2 | 8,335 | 1/12/2023 |
4.1.1 | 260 | 1/12/2023 |
4.1.0 | 502 | 12/26/2022 |
4.0.3 | 298 | 12/21/2022 |
4.0.2 | 717 | 11/22/2022 |
4.0.1 | 1,974 | 9/19/2022 |
4.0.0 | 528 | 9/5/2022 |
3.1.0 | 374 | 9/1/2022 |
3.0.1 | 2,266 | 12/9/2021 |
3.0.0 | 317 | 9/1/2021 |
2.0.3 | 371 | 8/17/2021 |
2.0.2 | 310 | 8/13/2021 |
2.0.1 | 312 | 8/6/2021 |
2.0.0 | 352 | 7/6/2021 |
1.4.2 | 301 | 6/28/2021 |
1.4.1 | 363 | 6/23/2021 |
1.3.1 | 339 | 6/15/2021 |
1.3.0 | 294 | 6/4/2021 |
1.2.0 | 289 | 6/2/2021 |
1.1.0 | 317 | 6/2/2021 |
1.0.1 | 349 | 4/22/2021 |
1.0.0 | 475 | 11/28/2020 |
1.0.0-alpha5 | 248 | 11/23/2020 |
1.0.0-alpha4 | 260 | 11/23/2020 |
1.0.0-alpha3 | 254 | 11/23/2020 |
1.0.0-alpha2 | 224 | 11/21/2020 |
1.0.0-alpha1 | 263 | 11/20/2020 |