JsonSchema.Net验证CycloneDX 1.6 Schema时无效文档无错误返回及手动注册子Schema的疑问
JsonSchema.Net验证CycloneDX 1.6 Schema时无效文档无错误返回及手动注册子Schema的疑问
我之前用JsonSchema.Net处理外部Schema的时候也踩过类似的坑,咱们一步步拆解你的问题:
一、为什么无效文档的HasErrors是False,但IsValid是False?
你这里其实是对EvaluationResults的两个属性含义理解错了:
IsValid:这个才是判断文档是否符合Schema的核心标志,你的输出里它已经正确返回了False,和预期一致。HasErrors:它不是指文档不符合Schema的验证规则,而是指验证过程中出现了异常问题——比如Schema本身语法错误、无法解析$ref引用、文档格式非法等。像必填项缺失、枚举值不匹配这类“文档不符合规则”的情况,属于验证失败,会被记录在results.Details集合里,并不会触发HasErrors为True。
如果你要给用户返回具体的验证错误,应该遍历results.Details获取详细信息,比如在你的代码里加这段:
foreach (var detail in results.Details) { Console.WriteLine($"- {detail.Message} (路径: {detail.InstanceLocation})"); }
运行后就能看到类似“缺少必填属性bomFormat”“bomFormat必须等于CycloneDX”的具体提示。
二、为什么要手动注册子Schema,而且你的注册方式错了!
CycloneDX 1.6的主Schema里引用了两个外部Schema(spdx.schema.json和jsf-0.82.schema.json的signature定义),JsonSchema.Net默认不会自动下载外部Schema,所以需要手动加载并注册到SchemaRegistry里——但你的注册逻辑完全搞错了!
你现在是把主CycloneDX Schema注册到了这两个外部Schema的URI上,这会导致主Schema里的$ref解析到错误的内容,甚至破坏整个验证逻辑。正确的做法是:
- 单独下载这两个外部Schema文件:
- 从CycloneDX的Schema仓库下载
spdx.schema.json - 下载
jsf-0.82.schema.json(或者直接提取其中的signature定义)
- 从CycloneDX的Schema仓库下载
- 分别加载这些Schema实例,再注册到对应的URI:
// 加载主Schema JsonSchema mainSchema = JsonSchema.FromFile("bom-1.6.schema.json"); // 加载并注册外部Schema // 1. 处理spdx.schema.json的引用 JsonSchema spdxSchema = JsonSchema.FromFile("spdx.schema.json"); SchemaRegistry.Global.Register(new Uri("http://cyclonedx.org/schema/spdx.schema.json"), spdxSchema); // 2. 处理jsf-0.82.schema.json#/definitions/signature的引用 JsonSchema jsfSchema = JsonSchema.FromFile("jsf-0.82.schema.json"); JsonSchema signatureSubSchema = jsfSchema.ResolveSubschema(new Uri("#/definitions/signature", UriKind.Relative)); SchemaRegistry.Global.Register(new Uri("http://cyclonedx.org/schema/jsf-0.82.schema.json#/definitions/signature"), signatureSubSchema);
这样主Schema里的$ref才能正确解析到对应的外部Schema内容,验证逻辑才会完整运行。
最后补充
你当前的代码因为错误注册了Schema,可能已经导致部分验证逻辑没有生效。按照上面的方式修正注册逻辑后,再结合遍历Details集合获取错误信息,就能完全符合你的预期了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

