C#中如何根据特定值隐藏JSON响应中的类属性?
当然可以搞定!不管你用的是老牌的Newtonsoft.Json(Json.NET)还是.NET Core之后自带的System.Text.Json,都有对应的办法实现基于属性特定值的条件序列化——也就是当属性值是你指定的内容时,自动从JSON响应里隐藏它。下面分两种情况给你讲具体做法:
这是很多项目常用的序列化库,有两种主流实现方式:
方式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);
如果你的项目用的是.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




