You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用JSchema动态校验扁平化JSON属性后生成合规JObject

实现通用扁平化JSON属性校验方案

你不需要先拼装完整JObject再执行校验,直接通过属性路径定位到JSchema中对应节点的约束,单条属性逐条校验即可,还能提前发现错误,不用等全量属性收集完成再处理。

核心实现步骤

  • 第一步:预加载JSchema并构建路径映射表
    先把从文件读取的JSchema解析为JSchema对象,递归遍历整个Schema结构,把所有合法的JSON路径和对应的Schema约束(类型、格式、枚举、范围等)存入字典,键统一使用点分隔的路径字符串,和你收到的属性路径格式完全匹配。
    注意处理数组类型的Schema:如果路径中包含数组项,比如UniversityCollection.Persons[*].Name,要把动态索引(比如Person1、Person2这类自定义标识)替换成通配符匹配规则,只要路径符合「前缀+索引后缀+后续路径」的格式,就匹配对应数组项的Schema约束。
  • 第二步:单条属性实时校验
    每条扁平化属性收到后直接执行以下操作:
    1. 拆分属性字符串,得到属性路径和属性值两部分
    2. 用属性路径去提前构建的Schema路径映射表里匹配对应的约束规则:
      • 匹配不到直接报错:该属性不符合Schema定义,属于非法字段
      • 匹配到的话,把属性值转换成Schema要求的类型(比如字符串转数字、布尔值、日期等),再校验是否符合约束(比如长度、数值范围、枚举值、格式要求等)
    3. 校验不通过直接抛出对应错误信息,包含具体属性路径、错误值、错误原因
  • 第三步:全量校验兜底
    等所有属性都校验完成、拼装成JObject之后,再用JSchema做一次全量整体校验,补漏单条属性校验覆盖不到的规则:比如必填字段缺失、字段之间的依赖约束、Schema的if/then/else逻辑等。

核心代码示例(基于Newtonsoft.Json.Schema)

using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using System.Text.RegularExpressions;

// 全局Schema路径映射表
Dictionary<string, JSchema> schemaPathMap = new Dictionary<string, JSchema>();

// 构建Schema路径映射的递归方法
void BuildSchemaPathMap(string currentPath, JSchema currentSchema)
{
    schemaPathMap[currentPath] = currentSchema;
    // 遍历对象属性
    foreach (var prop in currentSchema.Properties)
    {
        string childPath = string.IsNullOrEmpty(currentPath) ? prop.Key : $"{currentPath}.{prop.Key}";
        BuildSchemaPathMap(childPath, prop.Value);
    }
    // 处理数组项约束
    if (currentSchema.Items.Any())
    {
        string arrayItemPath = $"{currentPath}[*]";
        foreach (var itemSchema in currentSchema.Items)
        {
            BuildSchemaPathMap(arrayItemPath, itemSchema);
        }
    }
}

// 单条属性校验方法
bool ValidateSingleProperty(string propPath, string propValue, out string errorMsg)
{
    errorMsg = string.Empty;
    // 动态索引替换为通配符匹配Schema路径,可根据你的路径格式调整正则规则
    string matchPath = Regex.Replace(propPath, @"\.\w+\d+", match => $".[*]");
    if (!schemaPathMap.TryGetValue(matchPath, out var targetSchema))
    {
        errorMsg = $"属性{propPath}不存在于Schema定义中";
        return false;
    }
    // 转换值类型并校验约束
    JToken valueToken;
    try
    {
        valueToken = JToken.FromObject(Convert.ChangeType(propValue, targetSchema.Type.Value));
    }
    catch
    {
        errorMsg = $"属性{propPath}的值{propValue}类型不符合要求,要求类型为{targetSchema.Type}";
        return false;
    }
    return valueToken.IsValid(targetSchema, out IList<string> errors);
}

注意事项

  • 如果你的Schema包含additionalProperties: false约束,预构建映射表的时候要额外标记每个节点是否允许额外属性,匹配不到路径的时候先判断父节点是否允许额外属性,再决定是否报错。
  • 数组索引如果是数字格式(比如Persons[0].Name),正则匹配规则要对应调整适配你的路径格式。

内容的提问来源于stack exchange,提问作者Enrique González

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:15:02