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

运行时给定JSON Schema,如何反序列化为可加入ValueSet的C#可序列化对象?

解决方案:运行时JSON Schema验证与适配ValueSet的C#实现

针对你遇到的两个核心问题——Json.NET无法适配运行时JSON Schema反序列化和返回对象无法加入ValueSet,下面给出完整的实现方案:

一、依赖准备

首先需要安装Newtonsoft.Json和Newtonsoft.Json.Schema两个NuGet包,用于JSON Schema验证和动态JSON处理:

Install-Package Newtonsoft.Json
Install-Package Newtonsoft.Json.Schema

二、核心实现思路

1. 解决运行时Schema验证问题

我们不需要依赖编译时定义的类,而是用JSchema加载运行时传入的Schema,将输入JSON解析为JObject后直接执行验证逻辑,完全适配动态Schema场景。

2. 解决ValueSet兼容性问题

Json.NET返回的JObject虽然能序列化,但可能无法直接加入某些ValueSet(比如要求原生.NET类型的集合)。我们可以将验证后的JObject递归转换为ExpandoObject或Dictionary<string, object>——这两种类型都是.NET原生支持序列化的,且能轻松加入大多数集合(包括自定义ValueSet)。

三、完整函数代码

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using System;
using System.Collections.Generic;
using System.Dynamic;

public class JsonSchemaProcessor
{
    /// <summary>
    /// 验证输入字符串是否符合运行时JSON Schema,并返回可加入ValueSet的可序列化对象
    /// </summary>
    /// <param name="jsonInput">待验证的JSON字符串</param>
    /// <param name="schemaJson">运行时提供的JSON Schema字符串</param>
    /// <returns>符合Schema的可序列化对象(ExpandoObject类型)</returns>
    /// <exception cref="ArgumentException">当JSON不符合Schema或输入无效时抛出</exception>
    public static object ValidateAndGetValueSetCompatibleObject(string jsonInput, string schemaJson)
    {
        // 1. 加载并验证运行时Schema的合法性
        JSchema schema;
        try
        {
            schema = JSchema.Parse(schemaJson);
        }
        catch (JsonException ex)
        {
            throw new ArgumentException("传入的JSON Schema格式无效", nameof(schemaJson), ex);
        }

        // 2. 解析输入JSON并执行Schema验证
        JObject jsonObject;
        IList<string> validationErrors = new List<string>();
        try
        {
            jsonObject = JObject.Parse(jsonInput);
        }
        catch (JsonException ex)
        {
            throw new ArgumentException("输入的JSON字符串格式无效", nameof(jsonInput), ex);
        }

        bool isValid = jsonObject.IsValid(schema, out validationErrors);
        if (!isValid)
        {
            var errorDetails = string.Join(Environment.NewLine, validationErrors);
            throw new ArgumentException($"JSON不符合指定Schema:{Environment.NewLine}{errorDetails}");
        }

        // 3. 将JObject转换为ExpandoObject(兼容序列化和ValueSet)
        var expandoResult = new ExpandoObject();
        var expandoDict = (IDictionary<string, object>)expandoResult;

        foreach (var property in jsonObject.Properties())
        {
            expandoDict[property.Name] = ConvertJTokenToNativeObject(property.Value);
        }

        return expandoResult;
    }

    /// <summary>
    /// 递归将JToken转换为.NET原生可序列化对象,处理嵌套结构
    /// </summary>
    private static object ConvertJTokenToNativeObject(JToken token)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                var nestedExpando = new ExpandoObject();
                var nestedDict = (IDictionary<string, object>)nestedExpando;
                foreach (var prop in token.Children<JProperty>())
                {
                    nestedDict[prop.Name] = ConvertJTokenToNativeObject(prop.Value);
                }
                return nestedExpando;
            case JTokenType.Array:
                var itemList = new List<object>();
                foreach (var item in token.Children())
                {
                    itemList.Add(ConvertJTokenToNativeObject(item));
                }
                return itemList;
            case JTokenType.Integer:
            case JTokenType.Float:
            case JTokenType.String:
            case JTokenType.Boolean:
            case JTokenType.Null:
                return token.ToObject<object>();
            default:
                return token.ToString();
        }
    }
}

四、使用示例

// 运行时传入的Schema示例
string dynamicSchema = @"
{
  ""type"": ""object"",
  ""properties"": {
    ""Username"": { ""type"": ""string"" },
    ""Age"": { ""type"": ""integer"", ""minimum"": 16 },
    ""IsVerified"": { ""type"": ""boolean"" }
  },
  ""required"": [""Username"", ""Age""]
}";

// 待验证的JSON字符串
string validJson = @"{""Username"":""Bob"",""Age"":22,""IsVerified"":true}";

try
{
    var result = JsonSchemaProcessor.ValidateAndGetValueSetCompatibleObject(validJson, dynamicSchema);
    
    // 将结果加入ValueSet(这里用HashSet<object>模拟自定义ValueSet)
    var valueSet = new HashSet<object>();
    valueSet.Add(result);
    
    // 测试序列化功能
    string serializedJson = JsonConvert.SerializeObject(result);
    Console.WriteLine("序列化结果:" + serializedJson);
}
catch (ArgumentException ex)
{
    Console.WriteLine("处理失败:" + ex.Message);
}

关键说明

  • 动态Schema适配:通过JSchema.Parse加载运行时Schema,JObject.IsValid执行验证,完全摆脱编译时类的限制。
  • ValueSet兼容性:ExpandoObject实现了IDictionary<string, object>,既支持Json.NET序列化,也能直接加入绝大多数集合(包括自定义ValueSet)。如果你的ValueSet要求特定类型,也可以将转换逻辑改为返回Dictionary<string, object>,兼容性一致。
  • 嵌套结构处理:递归转换逻辑确保JSON中的嵌套对象、数组都能转换为.NET原生类型,避免序列化或集合加入时出现异常。

内容的提问来源于stack exchange,提问作者user9514066

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:12:30