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
相关产品推荐
相关产品推荐

