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

C#运行时动态填充动态对象属性适配JsonSchemaGenerator问题

解决动态生成Swagger JSON Schema的方案

方案一:用Dictionary<string, object>手动构建Schema

直接用字典存储动态属性,然后手动将字典键值对映射为Schema的对象属性,适配Swagger的生成要求:

var dynamicProps = new List<string> { "PropA", "PropB", "PropC" };
var dynamicDict = new Dictionary<string, object>();
foreach (var prop in dynamicProps)
{
    dynamicDict[prop] = default(string); // 根据实际业务设置属性的默认值/类型
}

// 生成并调整Schema
var generator = new JsonSchemaGenerator();
var schema = generator.Generate(dynamicDict.GetType());
schema.Type = JsonObjectType.Object;
schema.Properties.Clear();

foreach (var kvp in dynamicDict)
{
    var propSchema = generator.Generate(kvp.Value.GetType());
    schema.Properties.Add(kvp.Key, propSchema);
}

方案二:自定义动态类型实现ICustomTypeDescriptor

创建一个支持动态添加属性的自定义类,通过类型描述器让Schema生成器识别动态属性:

public class DynamicSchemaObject : ICustomTypeDescriptor
{
    private readonly Dictionary<string, Type> _propertyTypes = new();

    public void AddProperty(string name, Type type)
    {
        _propertyTypes[name] = type;
    }

    public PropertyDescriptorCollection GetProperties()
    {
        var props = new List<PropertyDescriptor>();
        foreach (var kvp in _propertyTypes)
        {
            props.Add(new DynamicPropertyDescriptor(kvp.Key, kvp.Value));
        }
        return new PropertyDescriptorCollection(props.ToArray());
    }

    // 实现ICustomTypeDescriptor的其他必要方法,返回默认值即可
    public AttributeCollection GetAttributes() => AttributeCollection.Empty;
    public string GetClassName() => nameof(DynamicSchemaObject);
    public string GetComponentName() => null;
    public TypeConverter GetConverter() => TypeDescriptor.GetConverter(GetType());
    public EventDescriptor GetDefaultEvent() => null;
    public PropertyDescriptor GetDefaultProperty() => null;
    public object GetEditor(Type editorBaseType) => null;
    public EventDescriptorCollection GetEvents() => EventDescriptorCollection.Empty;
    public EventDescriptorCollection GetEvents(Attribute[] attributes) => EventDescriptorCollection.Empty;
    public PropertyDescriptorCollection GetProperties(Attribute[] attributes) => GetProperties();
    public object GetPropertyOwner(PropertyDescriptor pd) => this;
}

public class DynamicPropertyDescriptor : PropertyDescriptor
{
    private readonly Type _propertyType;

    public DynamicPropertyDescriptor(string name, Type propertyType) : base(name, null)
    {
        _propertyType = propertyType;
    }

    public override bool CanResetValue(object component) => false;
    public override object GetValue(object component) => Activator.CreateInstance(_propertyType);
    public override void ResetValue(object component) { }
    public override void SetValue(object component, object value) { }
    public override bool ShouldSerializeValue(object component) => false;
    public override Type ComponentType => typeof(DynamicSchemaObject);
    public override bool IsReadOnly => false;
    public override Type PropertyType => _propertyType;
}

使用示例:

var dynamicProps = new List<string> { "PropA", "PropB" };
var dynamicObj = new DynamicSchemaObject();
foreach (var prop in dynamicProps)
{
    dynamicObj.AddProperty(prop, typeof(string)); // 指定属性类型
}

var generator = new JsonSchemaGenerator();
var schema = generator.Generate(dynamicObj.GetType());

方案三:适配ExpandoObject的Schema生成配置

如果坚持用ExpandoObject,可以通过自定义契约解析器让Schema生成器将其识别为普通对象:

public class ExpandoObjectContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        if (objectType == typeof(ExpandoObject))
        {
            return CreateObjectContract(objectType);
        }
        return base.CreateContract(objectType);
    }
}

使用示例:

var expando = (IDictionary<string, object>)new ExpandoObject();
var dynamicProps = new List<string> { "PropA", "PropB" };
foreach (var prop in dynamicProps)
{
    expando[prop] = default(int);
}

var generator = new JsonSchemaGenerator
{
    ContractResolver = new ExpandoObjectContractResolver()
};
var schema = generator.Generate(expando.GetType());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:35:15