首页 > 解决方案 > 如何从类型的给定属性中找到相应的 JsonSchema 属性?

问题描述

在 OpenAPI 中,您可以为字符串数组中的项目指定 maxLength。使用 DataAnnotations,您不能开箱即用地执行此操作,因此我为它创建了一个相当通用的自定义 ValidationAttribute(这是我现在要做的,只是为了让它工作)。

public class ArrayItemValidationAttribute : ValidationAttribute
{
    public ValidationAttribute ItemValidator { get; }

    public ArrayItemValidationAttribute(Type validatorType, params object[] args)
    {
        if (!typeof(ValidationAttribute).IsAssignableFrom(validatorType))
        {
            throw new Exception("The given validatorType does not derive from ValidationAttribute.");
        }
        ItemValidator = (ValidationAttribute)Activator.CreateInstance(validatorType, args);
    }


    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (!(value is Array array))
        {
            return new ValidationResult("Property is not an Array type.");
        }

        foreach (var item in array)
        {
            var vr = ItemValidator.GetValidationResult(item, validationContext);
            if (vr != null)
            {
                return new ValidationResult(vr.ErrorMessage);
            }
        }

        return ValidationResult.Success;
    }
}

我现在想将此传播到 OpenAPI 规范,该规范是使用 NSwag 从代码生成的。我正在使用 ISchemaProcessor,但我不知道如何从 Type 属性获取 JsonSchema 属性。

public class ArrayItemValidationProcessor : ISchemaProcessor
{
    public void Process(SchemaProcessorContext context)
    {
        foreach (var property in context.Type.GetProperties())
        {
            var attr = property.GetCustomAttribute<ArrayItemValidationAttribute>();
            if (attr != null)
            {
                context.Schema.Properties[/* What to fill in here? */]
            }
        }
    }
}

我在生成器上发现了 GetPropertyName,但这需要一个 JsonProperty 对象,所以我仍然遇到同样的问题。

我可以尝试自己从实际的属性名称和/或 JsonPropertyAttribute 数据中派生 json 模式属性名称,但如果实现会在未来版本中更改/扩展,我不想更新此代码,它应该继续工作.

编辑:到目前为止我能想到的最好的是:

var jsonProperty = context.Settings.ResolveContract(context.Type) is JsonObjectContract contract 
    ? contract.Properties.SingleOrDefault(x => x.UnderlyingName == property.Name)
    : null;
var propName = context.Generator.GetPropertyName(jsonProperty, property.ToContextualMember());
if (context.Schema.Properties.TryGetValue(propName, out var jsonSchemaProperty) && jsonSchemaProperty.IsArray) {
    // put maxLength on schema here.
}

还有其他想法吗?

标签: asp.net-coreasp.net-web-apinswagnjsonschema

解决方案


推荐阅读