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

如何在ASP.NET Core中绑定Swagger传入的动态模型?

解决方案:动态模型绑定实现

问题核心在于默认JSON序列化器无法自动根据JSON中的额外属性(如address/vendor)匹配对应的RequestItem子类,需要通过自定义JSON转换器实现类型识别与绑定。

步骤1:修正模型属性与JSON字段映射

确保C#属性名与JSON字段名严格匹配,可通过特性标记实现:

// System.Text.Json 特性
using System.Text.Json.Serialization;

public class UpdateRequestItems
{   
    public List<RequestItem> RequestItems { get; set; }
}

[JsonConverter(typeof(RequestItemConverter))] // 标记使用自定义转换器
public class RequestItem
{
    public Guid Id { get; set; }
    public DateOnly EventDate { get; set; }    
    public string EventName { get; set; }
    public EventType EventType { get; set; }
}

public class RequestAddress : RequestItem
{
    [JsonPropertyName("address")] // 匹配JSON中的"address"字段
    public TripItineraryAddress? Address { get; set; }
}

public class RequestVendor : RequestItem
{
    [JsonPropertyName("vendor")]
    public TripItineraryVendor? Vendor { get; set; }
}

public class RequestDescription : RequestItem
{
    [JsonPropertyName("description")]
    public TripItineraryDescription? Description { get; set; }
}

public class TripItineraryAddress
{
    [JsonPropertyName("address")]
    public string Address { get; set; }
    
    [JsonPropertyName("note")]
    public string Note { get; set; }
}

// 补充其他TripItineraryXXX类的属性映射

步骤2:实现自定义JSON转换器

创建RequestItemConverter,根据JSON中的属性或eventType值判断实例化的子类:

using System.Text.Json;
using System.Text.Json.Serialization;

public class RequestItemConverter : JsonConverter<RequestItem>
{
    public override RequestItem Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;

        // 优先通过EventType判断(更可靠)
        if (root.TryGetProperty("eventType", out JsonElement eventTypeElem) && 
            eventTypeElem.TryGetInt32(out int eventTypeVal))
        {
            return (EventType)eventTypeVal switch
            {
                EventType.AddressEvent => JsonSerializer.Deserialize<RequestAddress>(root.GetRawText(), options),
                EventType.VendorEvent => JsonSerializer.Deserialize<RequestVendor>(root.GetRawText(), options),
                EventType.DescriptionEvent => JsonSerializer.Deserialize<RequestDescription>(root.GetRawText(), options),
                _ => JsonSerializer.Deserialize<RequestItem>(root.GetRawText(), options)
            };
        }

        //  fallback:通过存在的属性判断
        if (root.TryGetProperty("address", out _))
            return JsonSerializer.Deserialize<RequestAddress>(root.GetRawText(), options);
        if (root.TryGetProperty("vendor", out _))
            return JsonSerializer.Deserialize<RequestVendor>(root.GetRawText(), options);
        if (root.TryGetProperty("description", out _))
            return JsonSerializer.Deserialize<RequestDescription>(root.GetRawText(), options);

        return JsonSerializer.Deserialize<RequestItem>(root.GetRawText(), options);
    }

    public override void Write(Utf8JsonWriter writer, RequestItem value, JsonSerializerOptions options)
    {
        // 序列化时根据实际类型输出
        JsonSerializer.Serialize(writer, value, value.GetType(), options);
    }
}

// 假设EventType枚举定义如下(需与业务实际值匹配)
public enum EventType
{
    AddressEvent = 1601,
    VendorEvent = 1602,
    DescriptionEvent = 1603
}

步骤3:配置转换器(可选)

如果未在基类上标记[JsonConverter],可在Program.cs/Startup.cs中全局配置:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new RequestItemConverter());
    });

验证

发送示例JSON请求后,UpdateRequestItems.RequestItems中的元素会被正确解析为对应的子类(如带address的项会是RequestAddress实例),子数据Address也会完成绑定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:55:39