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

How to use JsonSchema for real-time client-side validation?

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

当您使用 AJV and then check it again on the server using a PHP implementation of JSON Schema 单击提交时,我可以使用它来验证我的表单数据。

这部分听起来不错,但我想弄清楚我将如何使用它进行实时验证——即,在您填写 form/typing.[=13= 时进行验证]

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

有人为此目的使用过 JsonSchema 吗?可行吗?我如何将 AJV 或其他 JsonSchema 实现微调为仅 运行 input 上必需的验证器?

将其与客户端集成在很大程度上取决于您在客户端使用的是什么。我正在开发一个项目,在 Angular 2+ 和 AJV 中使用动态创建的表单,它运行得非常好。

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

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

一般来说,即使在我的具有多达 30-40 个输入值的更复杂的表单上,ajv 也需要不到 10 毫秒的时间来验证整个表单,包括我自己的一个函数,用于将 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))
  }
})