Eskema 是一个可以帮助您使用简单但功能强大的 API 验证动态数据的工具。

它最初的目的是验证来自 API 的动态 JSON,由用户输入或您可能需要验证动态数据的任何其他场景。但它并不局限于 JSON 数据,您可以验证任何类型的动态数据。

特点

  • 简单的API
  • 可组合 / 可扩展
  • Safe
  • 完全测试

入门

要使用此包,除了安装包或将其添加到 pubspec.yml 中,没有太多其他工作要做。有关如何操作的指南,请查看 安装说明

概念

验证器

Eskema 中的几乎所有内容都是 [验证器],它们是接收一个值并返回一个 [IResult] 的函数。

以下都是验证器

isType<String>();
listOfLength(2);
listEach(isType<String>());
all([isType<List>(), isListOfLength(2)]);

IResult

这是一个表示验证结果的类

用法

一个例子胜过千言万语,所以这里有几个简单的例子。
有关更详细的示例,请查看 /examples 文件夹。

简单示例

注意:如果您只想验证单个值,您可能不需要 Eskema

否则,让我们看看如何验证单个值。您可以单独使用验证器

final isString = isType<String>();
const result1 = isString('valid string');
const result2 = isString(123);

result1.isValid;  // true
result2.isValid;  // false
result2.expected; // String

或者您可以组合使用验证器

all([isType<String>(), isDate()]);     // all validators must be valid
or(isType<String>(), isType<int>());   // either validator must be valid
and(isType<String>(), isType<int>());  // both validator must be valid


// This validator checks that, the value is a list of strings, with length 2, and contains item "test"
all([
  isOfLength(2),                    // checks that the list is of length 2
  listEach(isTypeOrNull<String>()), // checks that each item is either string or null
  listContains('test'),             // list must contain value "test"
]);

// This validator checks a map against a eskema. Map must contain property 'books', 
// which is a list of maps that matches a sub-eskema. Subeskema validates that the map has a name which is a string
final matchesEskema = eskema({
  'books': listEach(
    eskema({
      'name': isType<String>(),
    }),
  ),
});
matchesEskema({'books': [{'name': 'book name'}]});

验证器

isType

此验证器检查值是否为特定类型

isType<String>();
isType<int>();
isType<double>();
isType<List>();
isType<Map>();

isTypeOrNull

此验证器检查值是否为特定类型或为 null

isTypeOrNull<String>();
isTypeOrNull<int>();

nullable

此验证器允许验证器接受 null 值

nullable(eskema({...}));
  • 上面的验证器允许 Map 或 null

eskema

最常见的用例可能是验证 JSON 或动态 Map。为此,您可以使用 eskema 验证器。

在此示例中,我们验证了一个具有可选字段和嵌套字段的 Map。

final validateMap = eskema({
  'name': isTypeString(),
  'address': nullable(
    eskema({
      'city': isTypeString(),
      'street': isTypeString(),
      'number': all([
        isTypeInt(),
        isMin(0),
      ]),
      'additional': nullable(
        eskema({
          'doorbel_number': Field([isTypeInt()])
        })
      ),
    })
  )
});

final invalidResult = validateMap.call({});
invalidResult.isValid;    // false
invalidResult.isNotValid; // true
invalidResult.expected;   // name -> String
invalidResult.message;    // Expected name -> String

final validResult = validateMap.call({ 'name': 'bobby' });
validResult.isValid;    // true
validResult.isNotValid; // false
validResult.expected;   // Valid

listEach

另一个常见的用例是验证动态 List。为此,您可以使用 listEach 类。

此示例验证提供的值是一个长度为 2 的 List,并且每个元素都必须是 int 类型

final isValidList = all([
    listOfLength(2),
    listEach(isTypeInt()),
]);

isValidList.validate(null).isValid;      // true
isValidList.validate([]).isValid;        // true
isValidList.validate([1, 2]).isValid;    // true
isValidList.validate([1, "2"]).isValid;  // false
isValidList.validate([1, "2"]).expected; // [1] -> int

附加验证器

有关验证器的完整列表,请查看 文档

自定义验证器

Eskemalib/src/validators.dart 中提供了一组常见的验证器。您不仅限于使用这些验证器,还可以非常轻松地创建自定义验证器。

让我们看看如何创建一个验证器来检查字符串是否匹配某个模式

Validator validateRegexp(RegExp regexp) {
  return (value) {
    return Result(
      isValid: regexp.hasMatch(value),  
      expected: 'match pattern $regexp', // the message explaining what this validator expected
    );
  };
}

如果您希望您构建的验证器成为包的一部分,请发送一个 PR,我会考虑添加它!!

更多示例

有关更多示例,请查看 /examples 文件夹。或者查看 文档

包名

Eskema 是巴斯克语中“Schema”(模式)的意思。我不知道该给包起什么名字,经过一番寻找,我找到了巴斯克语中“schema”的词,并决定使用它!

附加信息

  • 有关更多信息,请查看 文档
    结束。
  • 如果您发现错误,请提交一个 issue 或向我发送一个 PR。
  • 我们欢迎贡献,请随时提交修复、新功能、自定义验证器等...

GitHub

https://github.com/nombrekeff/eskema