如何使用JsonSchema进行实时客户端验证?

时间:2017-10-26 00:33:26

标签: javascript jsonschema ajv

我正在评估使用JSON Schema验证表单数据。

当您使用AJV点击提交时,我可以使用它来验证我的表单数据,然后使用PHP implementation of JSON Schema在服务器上再次检查它。

这部分听起来不错,但我正在试图弄清楚如何将它用于实时验证 - 即验证,因为你填写了表格/打字。

具体来说,我可以在每次击键时运行整个验证器,但是当只有一个输入发生变化时验证整个表单似乎很昂贵。特别是,任何基于AJAX的验证(例如用户名唯一性检查)都会过于频繁地发生。

有没有人为此目的使用过JsonSchema?这可行吗?我如何微调AJV或其他JsonSchema实现只运行input所需的验证器?

1 个答案:

答案 0 :(得分:1)

将此与客户端集成将在很大程度上取决于您在客户端使用的内容。我正在研究一个使用Angular 2+和AJV中动态创建的表单的项目,它的工作非常好。

它还取决于您使用的JSON Schema的数量。例如,我希望我的表单能够使用$data references,以便一个输入的有效性可以取决于其他输入的值。这基本上意味着我必须对表单中的任何更改进行验证,因为没有一种有效的方法来判断$ data引用的 target 是什么值。

此外,如果您的模型数据有可能在与表单交互的用户之外进行更改(例如,从其他用户从服务器中提取新数据等),则验证架构和模型完整。

一般来说,即使在我的更复杂的表格上,输入值高达30-40,ajv也需要不到10ms的时间来验证整个表格,包括我自己的功能,以便将ajv的错误与我的显示输入相匹配。所以我不担心性能损失。

编辑:对于异步验证器,添加某种去抖将取决于您使用客户端的内容,但不应过于刻板AJV's documentation is really complete

编辑:这是我遇到错误的循环以匹配它们并将它们清理一下(大多数AJV的错误都是用户可读的,但有些像模式匹配需要一些帮助而不是向用户吐出正则表达式):

errs.forEach((err) => {
  // Is this a value that is being matched to another input?
  if (err.dataPath === dataPath && err.keyword === 'const' && err.schema.$data) {
    return messages.push('Does not match')
  }

  // Don't show regex to people.
  else if (err.dataPath === dataPath && err.keyword === 'pattern') {
    return messages.push('Not valid format')
  }

  // Is the keyword 'required' and the parentPath is a match and the property is matched to err.params.missingProperty
  else if (err.keyword === 'required' && err.dataPath === parentPath && err.params.missingProperty === propertyName) {
    return messages.push('Required')
  }

  // Is the dataPath a match and no other special criteria apply
  else if (err.dataPath === dataPath) {
    // Cap first letter
    return messages.push(err.message.charAt(0).toUpperCase() + err.message.slice(1))
  }
})