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

.NET Core Web API如何将Selected为True的模型字段设为NULL?

问题描述

我有一个接收如下JSON(对应RequestModel)的.NET Core Web API:

{
    "isSpecimen": true,   
    "forms": {
        "cyber": {           
            "abc1": {
                "formOrder": 1,
                "endNumber": "1",
                "selected": true,
                "aggLimit": 5000000.0,
                "Date": "2016-12-14T00:00:00.00Z"
            },
            "abc2": {
                "formOrder": 2,
                "endNumber": "4",
                "selected": false,
                "aggLimit": 50000.0,
                "Date": "2019-12-14T00:00:00.00Z"
            }
        }
    }
}

对应的C#模型类如下:

public class RequestModel
{
   public FormsModel Forms { get; set; }
   public bool IsSpecimen { get; set; }
}

public abstract class BaseFormInfo
{
    public bool Selected { get; set; }
    public int? FormOrder { get; set; }
    public virtual string FormKey { get; set; }
}

public class FormsModel
{
    public ExcessFormsModel? Excess { get; set; }
    public CyberFormsModel? Cyber { get; set; }
}

public class CyberFormsModel
{
    public Abc1? abc1 { get; set; }
    public Abc2? abc2 { get; set; }
    public Abc3? abc3 { get; set; }
}

public class Abc1: BaseFormInfo
{
     public override string FormKey => "Abc1";
     public decimal? aggLimit{ get; set; }
     public DateTime? Date { get; set; }
     public string? endNumber{ get; set; }
}

需求:更新模型,将所有Selected字段为true的类的其他字段设为null,仅保留Selected: true。比如示例中abc1的Selected为true,需要把它的formOrder、endNumber、aggLimit、Date等字段都设为null。


解决方案

方案一:通过反射遍历已绑定的模型对象处理

适合在API接收模型后,直接操作实例化的对象:

1. 编写通用处理方法

递归遍历所有继承自BaseFormInfo的对象,检查Selected属性,若为true则清空其他可空字段:

using System.Reflection;

public static void ClearExtraFieldsWhenSelected<T>(T model) where T : class
{
    if (model == null) return;

    // 获取当前对象的所有公开实例属性
    var properties = model.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (var prop in properties)
    {
        var propValue = prop.GetValue(model);
        if (propValue == null) continue;

        // 处理BaseFormInfo子类对象
        if (typeof(BaseFormInfo).IsAssignableFrom(propValue.GetType()))
        {
            var formInfo = (BaseFormInfo)propValue;
            if (formInfo.Selected)
            {
                // 筛选出除Selected外的可空属性(值类型需为可空,引用类型直接处理)
                var formProperties = formInfo.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
                    .Where(p => p.Name != nameof(BaseFormInfo.Selected) && 
                                (Nullable.GetUnderlyingType(p.PropertyType) != null || p.PropertyType.IsClass));

                foreach (var formProp in formProperties)
                {
                    formProp.SetValue(formInfo, null);
                }
            }
        }
        // 递归处理嵌套的复杂对象(比如FormsModel、CyberFormsModel这类容器)
        else if (!prop.PropertyType.IsValueType && prop.PropertyType != typeof(string))
        {
            ClearExtraFieldsWhenSelected(propValue);
        }
    }
}

2. 在API接口中调用

[HttpPost]
public IActionResult ProcessRequest([FromBody] RequestModel request)
{
    // 执行字段清空逻辑
    ClearExtraFieldsWhenSelected(request);

    // 后续业务逻辑处理
    return Ok(request);
}

方案二:在JSON反序列化阶段自动处理

如果希望在JSON转模型的过程中直接完成处理,可以自定义JSON转换器(以Newtonsoft.Json为例):

1. 编写BaseFormInfo的自定义转换器

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class BaseFormInfoConverter : JsonConverter<BaseFormInfo>
{
    public override BaseFormInfo ReadJson(JsonReader reader, Type objectType, BaseFormInfo existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jsonObj = JObject.Load(reader);
        var selected = jsonObj[nameof(BaseFormInfo.Selected)]?.Value<bool>() ?? false;

        // 先完成基础反序列化
        var formInfo = jsonObj.ToObject(objectType) as BaseFormInfo;
        if (formInfo == null) return null;

        // 如果Selected为true,清空其他可空字段
        if (selected)
        {
            var properties = objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                .Where(p => p.Name != nameof(BaseFormInfo.Selected) && 
                            (Nullable.GetUnderlyingType(p.PropertyType) != null || p.PropertyType.IsClass));

            foreach (var prop in properties)
            {
                prop.SetValue(formInfo, null);
            }
        }

        return formInfo;
    }

    public override void WriteJson(JsonWriter writer, BaseFormInfo value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

2. 注册转换器

有两种注册方式:

  • 方式一:在BaseFormInfo类上标记特性
[JsonConverter(typeof(BaseFormInfoConverter))]
public abstract class BaseFormInfo
{
    // 原有代码
}
  • 方式二:全局注册(Program.cs)
builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.Converters.Add(new BaseFormInfoConverter());
    });

注意事项
  1. 两种方案都依赖字段为可空类型(比如int?、decimal?、string?),如果有非可空值类型需要处理,需额外调整逻辑设置默认值(但需求要求设为null,所以非可空值类型需要先改为可空)。
  2. 若使用System.Text.Json,自定义转换器的写法略有不同,但核心递归检查、清空字段的逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:57:10