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

5

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

我可以使用AJV在提交表单时进行验证,然后使用JSON Schema的PHP实现在服务器上再次检查它。

这部分听起来很棒,但我正在尝试弄清楚如何在实时验证中使用它--即,在填写表单/输入时进行验证。

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

有人用JsonSchema做过这个吗?可行吗?如何微调AJV或另一个JsonSchema实现,以仅在输入时运行必要的验证程序?

1个回答

2
将此翻译成中文:

将其与客户端集成将严重依赖于您在客户端使用的内容。我正在使用动态创建表单的 Angular 2+ 和 AJV 项目上使用此功能,效果非常好。

它还将根据您使用的 JSON Schema 的数量而有所不同。例如,我希望我的表单能够使用$data references,以便一个输入的有效性取决于其他输入的值。这基本上意味着我必须在表单中的任何更改上进行验证,因为没有一种有效的方法来确定哪个值是 $data 引用的目标。

此外,如果您的模型数据可能在用户与表单交互之外发生变化(例如,从其他用户那里拉取新数据等),则完全验证模式和模型更具韧性。

通常,即使在我的更复杂的表单中,包括我自己的函数来匹配 ajv 的错误以显示我的输入,ajv 验证整个表单也不到 10 毫秒。所以我不会担心性能问题。

编辑:关于异步验证器,添加一个防抖动的功能取决于您在客户端使用的是什么,但不应该太难。AJV的文档非常完整

编辑: 这是我用来匹配和清理错误的循环(大多数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))
  }
})

听起来不错。我正在使用React来构建我的用户界面。你能分享一下你用于将错误匹配到输入的函数吗?这正是我现在试图弄清楚的问题。特别是,“required”关键字似乎有些棘手,因为它与对象而非属性相关联。 - mpen
1
@mpen 这个函数与Angular的表单耦合度太高,我无法清理它,但在必填错误的情况下,缺失的属性将作为params.missingProperty传递给ajv错误对象,这将让你将其分配给正确的控件/输入。以下是类型接口,以便你了解其形状:https://github.com/epoberezkin/ajv/blob/master/lib/ajv.d.ts#L203 - Roy Reiss
你是在将错误与字段匹配时只解析 dataPath 吗?基本上只是按句点分割吗? - mpen
@mpen 是的。Ajv的数据路径使用正斜杠作为分隔符。我发了一个清理循环的示例,可以匹配特定的错误,比如“required”。 - Roy Reiss
太好了!感谢你的建议。 - mpen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接