You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

C#中如何根据特定值隐藏JSON响应中的类属性?

当然可以搞定!不管你用的是老牌的Newtonsoft.Json(Json.NET)还是.NET Core之后自带的System.Text.Json,都有对应的办法实现基于属性特定值的条件序列化——也就是当属性值是你指定的内容时,自动从JSON响应里隐藏它。下面分两种情况给你讲具体做法:

使用Newtonsoft.Json(Json.NET)的方案

这是很多项目常用的序列化库,有两种主流实现方式:

方式1:ShouldSerialize命名约定(推荐)

这种方式最直观,不需要额外配置,Json.NET会自动识别符合ShouldSerialize+属性名命名规则的方法,方法返回false就会跳过该属性的序列化。

比如你的实体类可以这么写:

public class SportsPerson
{
    public string Name { get; set; }
    public string SportType { get; set; }

    // 命名必须是 ShouldSerialize + 属性名(首字母大写)
    public bool ShouldSerializeSportType()
    {
        // 这里定义条件:只有当SportType不等于"Tennis"时才序列化
        return SportType != "Tennis";
    }
}

序列化的时候,你原来的NullValueHandling.Ignore配置依然有效,直接正常序列化即可:

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore
};
var json = JsonConvert.SerializeObject(yourSportsPersonInstance, settings);

方式2:自定义ContractResolver(全局规则适用)

如果你需要给多个类统一设置相同的序列化条件,或者不想在实体类里添加额外方法,可以用自定义契约解析器:

public class CustomSportContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        // 针对SportType属性设置条件
        if (property.PropertyName.Equals("SportType", StringComparison.OrdinalIgnoreCase))
        {
            property.ShouldSerialize = instance =>
            {
                // 获取当前对象的SportType属性值
                var sportType = instance.GetType().GetProperty("SportType")?.GetValue(instance) as string;
                // 返回true才序列化,这里就是值不为"Tennis"时保留
                return sportType != "Tennis";
            };
        }

        return property;
    }
}

使用时把契约解析器加到序列化配置里:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CustomSportContractResolver(),
    NullValueHandling = NullValueHandling.Ignore
};
var json = JsonConvert.SerializeObject(yourObject, settings);
使用System.Text.Json的方案(.NET Core 3.0+)

如果你的项目用的是.NET自带的序列化库,分两种版本情况处理:

方式1:ShouldSerialize命名约定(.NET 5及以上推荐)

从.NET 5开始,System.Text.Json也支持了和Json.NET类似的ShouldSerialize命名规则,写法几乎一样:

public class SportsPerson
{
    public string Name { get; set; }
    public string SportType { get; set; }

    // System.Text.Json 会自动识别这个方法
    public bool ShouldSerializeSportType()
    {
        return SportType != "Tennis";
    }
}

序列化时保留你原来的忽略null配置:

var options = new JsonSerializerOptions
{
    IgnoreNullValues = true // 对应原来的NullValueHandling.Ignore
};
var json = JsonSerializer.Serialize(yourSportsPersonInstance, options);

方式2:自定义JsonConverter(.NET Core 3.x兼容)

如果你还在使用.NET Core 3.x(不支持ShouldSerialize),可以写一个自定义转换器来控制序列化逻辑:

public class SportsPersonConverter : JsonConverter<SportsPerson>
{
    // 反序列化逻辑,如果不需要自定义可以按默认实现
    public override SportsPerson Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        return JsonSerializer.Deserialize<SportsPerson>(doc.RootElement.GetRawText(), options);
    }

    // 自定义序列化逻辑
    public override void Write(Utf8JsonWriter writer, SportsPerson value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();

        // 序列化Name属性
        if (value.Name != null)
        {
            writer.WriteString("Name", value.Name);
        }

        // 只有当SportType不是"Tennis"时才序列化
        if (value.SportType != "Tennis")
        {
            writer.WriteString("SportType", value.SportType);
        }

        writer.WriteEndObject();
    }
}

使用时把转换器加到配置里:

var options = new JsonSerializerOptions
{
    IgnoreNullValues = true,
    Converters = { new SportsPersonConverter() }
};
var json = JsonSerializer.Serialize(yourSportsPersonInstance, options);

总的来说,ShouldSerialize命名约定是最简洁的实现方式,适合大多数场景;如果需要全局统一规则或者兼容老版本框架,再考虑自定义契约解析器或转换器。

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

火山引擎 最新活动