Flutter数据验证插件valid_value_objects的使用

Flutter数据验证插件valid_value_objects的使用

Dart包用于创建具有类型安全性和可读性的不可变验证值对象。

目录

概述

你可能已经熟悉来自DDD概念的值对象。 值对象提供了以下功能:

  • 不可变性
  • 类型安全性
  • 代码可读性
  • 验证
    • 只有当输入参数有效时,对象才会被实例化。
    • 使无效的值对象不可表示。

该包提供了以下值对象:

  • EmailAddress
  • IPAddress
  • ISBN
  • Name, FirstName, MiddleName, LastName
  • Password
  • PhoneNumber
  • UniqueId, TimeId

注意: 通过扩展ValueObject类来创建自己的值对象。

异常

以下是创建值对象时可能出现的一些异常示例:

可能的异常

  • RequiredValueException
  • InvalidValueException
  • TooShortValueException
  • TooLongValueException

注意: 上述所有异常都是ValueException的实例。

对象创建

EmailAddress

EmailAddress 实例化:

try {
  EmailAddress e = EmailAddress('example[@gmail](/user/gmail).com');
} on RequiredValueException {
  // 如果参数为null或空,则会发生此情况
} on InvalidValueException {
  // 如果参数不匹配正则表达式,则会发生此情况
}

// 或者一次性处理所有异常:

try {
   EmailAddress e = EmailAddress('example[@gmail](/user/gmail).com');
} on ValueException catch (e) {  
  // 捕获所有值异常
  print(e.invalidValue);
  print(e.code);
  print(e.message);
}

// 或者完全不处理异常,如果你确定值是正确的。

自定义

密码

您可能希望配置默认的密码要求。

// 一个接一个地设置要求:

Password.minChar = ...;
Password.maxChar = ...;
Password.mustContainUpperChar = ...;
Password.mustContainNumeric = ...;
...

// 或者可以使用以下方法设置:

Password.setRequirements(
  minChar: 10, // 默认: 8
  maxChar: 50, // 默认: 255
  mustContainLowerChar: false, // 默认: true
  mustContainNumeric: false, // 默认: true
  mustContainUpperChar: false, // 默认: true
  mustContainSpecialChar: false, // 默认: false
);

自定义验证器

EmailAddress.customValidator = (str) => str.contains('@');   
PhoneNumber.customValidator = (str) { ... };
FirstName.customValidator = (str) => ...;

如果您定义了一个customValidator,则类的工厂构造函数和验证函数将使用您的自定义验证器而不是默认的验证器。

序列化

以上验证和类型安全性使得每个值对象都提供了toJsonfromJson方法。因此,将它们存储在NoSQL数据库中很容易。该包与json_serialization包兼容,但该包本身并不依赖于它。

自定义key字段(如果需要)。每个值对象都有一个static key字段,这些字段由toJsonfromJson函数使用。

默认键:

  • EmailAddress: “email”
  • Name: “name”
  • FirstName: “firstName”
  • MiddleName: “middleName”
  • LastName: “lastName”
  • IPAddress: “ip”
  • ISBN: “isbn”
  • Password: “password”
  • PhoneNumber: “phone”
  • UniqueId: “id”

在嵌套的Map对象中查找key?没问题。

const simpleMap = {'email' : 'xy[@gmail](/user/gmail).com'};
const nestedMap = {
  'person' : {
    'contact' : {
      'phone' : '...',
      'email' : 'xy[@gmail](/user/gmail).com',
    },
  },
};

EmailAddress.fromJson(simpleMap) == EmailAddress.fromJson(nestedMap) // true

请参阅示例文件夹以获取更多说明。

如果您有任何功能请求或对包有一些有用的想法,请随时打开一个问题:

// 示例代码
import 'package:json_annotation/json_annotation.dart';
import 'package:valid_value_objects/valid_value_objects.dart';

part 'example.g.dart';

const userMap = {
  'userId': '2020-10-31 11:43:44.551947',
  'phone': '06301234567',
  'email': 'xy[@gmail](/user/gmail).com',
  'firstName': 'Ab',
  'lastName': 'Xy',
};

const nestedUserMap = {
  'a': {'userId': '2020-10-31 11:43:44.551947'},
  'b': {
    'c': {'phone': '06301234567'},
    'd': {'email': 'xy[@gmail](/user/gmail).com'}
  },
  'name': {
    'firstName': 'Ab',
    'lastName': 'Xy',
  },
};

class User {
  final UniqueId userId;
  PhoneNumber phone;
  EmailAddress email;
  FirstName firstName;
  LastName lastName;

  User(this.userId, this.phone, this.email, this.firstName, this.lastName);

  factory User.fromJson(Map<String, dynamic> json) {
    final id = UniqueId.fromJson(json);
    final phone = PhoneNumber.fromJson(json);
    final email = EmailAddress.fromJson(json);
    final fn = FirstName.fromJson(json);
    final ln = LastName.fromJson(json);

    return User(id, phone, email, fn, ln);
  }

  Map<String, dynamic> toJson() {
    return {
      UniqueId.key: userId,
      PhoneNumber.key: phone,
      EmailAddress.key: email,
      FirstName.key: firstName,
      LastName.key: lastName,
    };
  }
}

// 兼容json_serializable库
[@JsonSerializable](/user/JsonSerializable)()
class User2 {
  final UniqueId userId;
  PhoneNumber phone;
  EmailAddress email;
  FirstName firstName;
  LastName lastName;

  User2(this.userId, this.phone, this.email, this.firstName, this.lastName);

  factory User2.fromJson(Map<String, dynamic> json) => _$User2FromJson(json);

  Map<String, dynamic> toJson() => _$User2ToJson(this);
}

void main() {
  // 如果需要更改默认的key变量
  UniqueId.key = 'userId';

  final user = User.fromJson(userMap);
  print(user.toJson());

  final user2 = User2.fromJson(userMap);
  print(user2.toJson());

  // 使用值对象的fromJson构造函数也可以找到嵌套的key
  final user3 = User.fromJson(nestedUserMap);
  print(user3.toJson());

  // 自定义验证器示例:
  const sampleEmail = 'xy[@gmail](/user/gmail)';
  try {
    EmailAddress(sampleEmail);
  } on ValueException {
    print('This is an invalid email address (will be printed)');
  }

  EmailAddress.customValidator = (str) => str.contains('@');

  try {
    EmailAddress(sampleEmail);
  } on ValueException {
    print('This is now a valid email address (will NOT be printed)');
  }
}

更多关于Flutter数据验证插件valid_value_objects的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据验证插件valid_value_objects的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


valid_value_objects 是一个用于 Flutter 的数据验证插件,它提供了一种简洁的方式来验证和封装值对象(Value Objects)。值对象是领域驱动设计(DDD)中的一个概念,通常用于封装具有特定业务含义的数据,并确保其有效性。

安装

首先,你需要在 pubspec.yaml 文件中添加 valid_value_objects 插件的依赖:

dependencies:
  valid_value_objects: ^0.0.1

然后运行 flutter pub get 来安装依赖。

使用

valid_value_objects 插件提供了一些基类来帮助你创建值对象,并自动处理验证逻辑。以下是一个简单的使用示例:

1. 创建值对象

假设你想创建一个表示电子邮件地址的值对象 Email,并确保它符合电子邮件格式。你可以通过继承 ValueObject 类来实现:

import 'package:valid_value_objects/valid_value_objects.dart';

class Email extends ValueObject<String> {
  Email(String value) : super(value, [EmailValidator()]);

  @override
  String toString() => value;
}

2. 创建验证器

接下来,你需要创建一个验证器来验证电子邮件地址的格式。你可以通过实现 Validator 接口来创建自定义验证器:

import 'package:valid_value_objects/valid_value_objects.dart';

class EmailValidator implements Validator<String> {
  @override
  void validate(String value) {
    final emailRegex = RegExp(r'^[^@]+@[^@]+\.[^@]+');
    if (!emailRegex.hasMatch(value)) {
      throw ValidationException('Invalid email format');
    }
  }
}

3. 使用值对象

现在你可以使用 Email 值对象来封装和验证电子邮件地址:

void main() {
  try {
    final email = Email('test@example.com');
    print('Valid email: ${email.value}');
  } on ValidationException catch (e) {
    print('Validation failed: ${e.message}');
  }

  try {
    final invalidEmail = Email('invalid-email');
    print('Valid email: ${invalidEmail.value}');
  } on ValidationException catch (e) {
    print('Validation failed: ${e.message}');
  }
}

输出

Valid email: test@example.com
Validation failed: Invalid email format
回到顶部