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

Posted

技术标签:

【中文标题】如何使用 JsonSchema 进行实时客户端验证?【英文标题】:How to use JsonSchema for real-time client-side validation? 【发布时间】:2018-04-07 05:29:31 【问题描述】:

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

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

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

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

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

【问题讨论】:

【参考方案1】:

将此与客户端集成在很大程度上取决于您在客户端使用的内容。我正在开发一个项目,在 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))
  
)

【讨论】:

很高兴听到这个消息。我正在为我的 UI 使用 React。您能否分享您将错误与输入匹配的功能?这就是我现在想要弄清楚的。特别是,“required”关键字似乎很尴尬,因为它与对象相关联,而不是与属性相关联。 @mpen 该函数与 Angular 的表单过于耦合,我无法清理,但在需要错误的情况下,缺少的属性作为 params.missingProperty 在 ajv 错误对象中传递,这将使您将其分配给正确的控制/输入。这是类型界面,可让您了解其形状:github.com/epoberezkin/ajv/blob/master/lib/ajv.d.ts#L203 为了将错误与字段匹配,您是否只是解析dataPath?基本上只是按时期分开? @mpen 是的。 Ajv 的数据路径使用正斜杠作为分隔符。作为一个例子,我发布了清理并匹配某些错误(如 required)的循环。 完美!感谢您的提示。

以上是关于如何使用 JsonSchema 进行实时客户端验证?的主要内容,如果未能解决你的问题,请参考以下文章

对于具有递归$ ref的JSONSchema,ajv验证失败

Json Schema 快速入门

Jsonschema测试实践

使用 JsonSchema 验证 API 的返回格式

Python jsonschema 验证时区

通过JSONSchema完成接口自动化测试的数据验证