C#中如何基于元Schema校验扩展后的JSON Schema合规性
C#环境下自定义扩展JSON Schema合规校验实现方案
整体校验逻辑设计
整个校验流程拆成两层串行执行,两层都通过才算合规:
- 第一层:语法合规校验。基于JSON Schema 2020-12版的元Schema规则,校验用户提交的扩展Schema本身语法合法,不会出现结构错误导致下游流程解析失败
- 第二层:业务规则留存校验。对比程序内置的默认基础Schema,严格落实“仅允许新增扩展、不允许删除原有核心要求”的规则
依赖选型
直接使用NuGet包JsonSchema.Net实现对应能力,该库内置了JSON Schema各版本的元Schema校验能力,不需要自行维护外部规则文件,天然支持draft 2020-12规范的语法校验。
安装命令:
Install-Package JsonSchema.Net
核心实现步骤
- 预加载固定内置基准
将默认基础Schema作为程序内置资源固化,不允许通过外部配置修改,提前提取两个校验基准集合:- 基础Schema中
properties节点下所有定义的核心属性名集合 - 基础Schema中
required节点下所有的强制必填属性名集合
- 基础Schema中
- 执行语法合法性校验
直接调用库内置的draft 2020-12元Schema实例,对用户提交的扩展Schema做语法合规校验,排查类似type值不合法、required字段结构错误这类Schema本身的语法问题。 - 执行核心留存规则校验
按照规则做硬性比对,不做弹性放宽:- 逐一遍历基准属性名集合,检查待校验扩展Schema的同层级
properties节点下是否存在同名属性,任意一个核心属性缺失就直接判定不合规 - 逐一遍历基准必填集合,检查待校验扩展Schema的同层级
required数组中是否完整保留所有原必填项,任意一个原必填项被移除就直接判定不合规 - 校验逻辑不限制两类操作:允许在
properties下新增自定义属性定义,允许在required数组中追加新增属性的必填要求
- 逐一遍历基准属性名集合,检查待校验扩展Schema的同层级
核心代码示例
// 从程序内置资源读取固定的默认基础Schema,无外部修改入口 var baseSchema = JsonSchema.FromText(内置默认Schema的JSON字符串); // 提取校验基准 var baseCorePropertyNames = baseSchema.Properties!.Keys.ToHashSet(); var baseRequiredFieldNames = baseSchema.Required!.ToHashSet(); // 获取用户提交的待校验扩展Schema var submittedExtSchema = JsonSchema.FromText(用户提交的扩展SchemaJSON); // 第一层:元Schema语法校验 var draftMetaSchema = JsonSchema.Draft202012; var syntaxCheckResult = draftMetaSchema.Evaluate(submittedExtSchema); if (!syntaxCheckResult.IsValid) { var errMsg = string.Join(";", syntaxCheckResult.Errors.Values); throw new InvalidOperationException($"Schema语法不合法:{errMsg}"); } // 第二层:核心属性留存校验 var missingCoreProps = baseCorePropertyNames.Except(submittedExtSchema.Properties!.Keys).ToList(); if (missingCoreProps.Any()) { var errProps = string.Join("、", missingCoreProps); throw new InvalidOperationException($"未完整留存基础核心属性,缺失字段:{errProps}"); } // 第三层:必填要求留存校验 var removedRequiredFields = baseRequiredFieldNames.Except(submittedExtSchema.Required!).ToList(); if (removedRequiredFields.Any()) { var errFields = string.Join("、", removedRequiredFields); throw new InvalidOperationException($"违规移除了原有强制必填要求,涉及字段:{errFields}"); } // 所有校验通过即可正常提交流程
落地注意事项
- 校验过程返回的错误信息要明确对应到具体的缺失/违规字段,不要笼统提示校验失败,方便前端表单开发者快速定位问题
- 不强制要求扩展Schema和基础Schema的属性定义完全一致,允许开发者在原有核心属性上补充描述、扩展子校验规则,只要不删除核心属性本身即可
- 固定基准Schema的加载路径要做权限隔离,避免被外部篡改后绕过校验逻辑
内容的提问来源于stack exchange,提问作者Sinan Barut
相关产品推荐
相关产品推荐

