当前位置: 首页 > news >正文

Newtonsoft.Json属性控制全攻略:从忽略到重命名的5种高级用法

Newtonsoft.Json属性控制全攻略:从忽略到重命名的5种高级用法

在C#开发中,处理JSON数据几乎成了日常工作的标配。Newtonsoft.Json(现也称Json.NET)作为.NET生态中最受欢迎的JSON库,其灵活性和强大功能让开发者爱不释手。但你是否真正掌握了它那些藏在细节里的高级特性?今天我们就来深入探讨那些能让你的JSON处理更优雅、更高效的属性控制技巧。

1. 属性忽略的艺术

属性忽略看似简单,实则暗藏玄机。最基本的用法是通过[JsonIgnore]特性标记不需要序列化的属性:

public class UserProfile { public string Username { get; set; } [JsonIgnore] public string PasswordHash { get; set; } // 安全考虑,不序列化 }

但实际开发中,我们经常遇到更复杂的情况。比如,某个属性可能在某些场景下需要序列化,在其他场景下又需要忽略。这时可以使用ShouldSerialize方法模式:

public class Order { public decimal TotalAmount { get; set; } public bool IsDiscounted { get; set; } public bool ShouldSerializeTotalAmount() { return !IsDiscounted; // 只有在未打折时才序列化总金额 } }

更灵活的方式是使用条件序列化:

public class Product { public string Name { get; set; } public decimal Price { get; set; } [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public decimal? DiscountedPrice { get; set; } // 为null时不序列化 }

提示:NullValueHandling.Ignore不仅能减少JSON体积,还能避免前端处理不必要的null值。

2. 属性重命名的巧妙应用

JSON属性名与C#属性名不一致时,[JsonProperty]就派上用场了。这在对接第三方API时特别常见:

public class WeatherData { [JsonProperty("temp_c")] public decimal TemperatureCelsius { get; set; } [JsonProperty("wind_kph")] public decimal WindSpeed { get; set; } }

更高级的用法是动态重命名。假设我们需要根据当前文化设置决定使用哪个字段名:

public class LocalizedProduct { private string _name; [JsonProperty("name")] public string Name { get => CultureInfo.CurrentCulture.Name == "zh-CN" ? $"产品_{_name}" : _name; set => _name = value; } }

对于枚举值的序列化控制,Newtonsoft.Json也提供了优雅的解决方案:

public enum UserRole { [JsonProperty("admin")] Administrator, [JsonProperty("user")] StandardUser, [JsonProperty("guest")] GuestUser } public class User { public UserRole Role { get; set; } }

3. 默认值处理的智慧

处理默认值能显著优化JSON数据大小和清晰度。Newtonsoft.Json提供了多种方式控制默认值的序列化行为。

最基本的用法是指定默认值:

public class Settings { [DefaultValue(10)] public int MaxRetryCount { get; set; } = 10; }

更精细的控制可以通过DefaultValueHandling实现:

public class Configuration { [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public int CacheSize { get; set; } // 默认值0时不序列化 [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] public bool EnableLogging { get; set; } = true; // 反序列化时会填充默认值 }

对于复杂对象的默认值处理,可以结合ShouldSerialize方法:

public class ReportOptions { public DateTime StartDate { get; set; } = DateTime.Today.AddMonths(-1); public DateTime EndDate { get; set; } = DateTime.Today; public bool ShouldSerializeStartDate() => StartDate != DateTime.Today.AddMonths(-1); public bool ShouldSerializeEndDate() => EndDate != DateTime.Today; }

4. 序列化与反序列化的不对称控制

有时我们需要属性在序列化时被忽略,但在反序列化时能够接收值。这种不对称控制可以通过私有属性和[JsonProperty]的组合实现:

public class SecureData { [JsonIgnore] public string ApiKey { get; set; } [JsonProperty("api_key")] private string ApiKeyForDeserialization { set => ApiKey = Decrypt(value); // 反序列化时解密 } private string Decrypt(string value) => /* 解密逻辑 */; }

另一种常见场景是只读属性的处理:

public class CalculatedResult { public decimal Value1 { get; set; } public decimal Value2 { get; set; } [JsonProperty] public decimal Sum => Value1 + Value2; // 序列化但不反序列化 // 防止反序列化时出错 private decimal SumForDeserialization { set { /* 忽略或特殊处理 */ } } }

对于集合属性,我们可能希望反序列化时总是新建集合而非替换现有引用:

public class Team { private List<Member> _members = new List<Member>(); [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Reuse)] public List<Member> Members { get => _members; set => _members = value ?? new List<Member>(); } }

5. 高级自定义与性能优化

当内置特性无法满足需求时,我们可以通过自定义JsonConverter实现完全控制:

public class UnixDateTimeConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var date = (DateTime)value; writer.WriteValue((date - new DateTime(1970,1,1)).TotalSeconds); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return new DateTime(1970,1,1).AddSeconds((long)reader.Value); } public override bool CanConvert(Type objectType) => objectType == typeof(DateTime); } public class Event { [JsonConverter(typeof(UnixDateTimeConverter))] public DateTime Timestamp { get; set; } }

对于性能敏感的场景,可以使用契约解析器(ContractResolver)预先定义序列化规则:

public class LowercaseContractResolver : DefaultContractResolver { protected override string ResolvePropertyName(string propertyName) { return propertyName.ToLower(); } } // 使用方式 var settings = new JsonSerializerSettings { ContractResolver = new LowercaseContractResolver() }; var json = JsonConvert.SerializeObject(obj, settings);

最后,别忘了利用ReferenceLoopHandling处理循环引用问题:

var settings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, PreserveReferencesHandling = PreserveReferencesHandling.Objects };
http://www.jsqmd.com/news/525227/

相关文章:

  • 2026汉中靠谱装修公司精选|品质整装设计定制高性价比全测评 - 一个呆呆
  • Audio Pixel StudioStreamlit性能压测:10并发TTS请求响应时间与稳定性
  • ESP8266 MQTT透传固件:从零到一的自定义烧录与智能配网实战
  • UART、IIC、SPI:嵌入式开发中的串行通信协议选型指南
  • SAP Smartforms打印问题解决:货币和数量字段显示异常的终极指南
  • 终极指南:5步完成老旧Mac升级与显卡驱动修复
  • 漫画脸生成数据可视化:MySQL存储与分析实战
  • 架构革命:11倍性能突破的轻量级无头浏览器如何重新定义自动化边界
  • CHORD-X系统重装系统后的快速恢复部署指南
  • 解锁AD9122的隐藏技能:用Zynq PL实现多模式信号调制的5个关键技巧
  • 2026年全自动多片锯选购指南:五大实力工厂深度解析与避坑建议 - 2026年企业推荐榜
  • 使用springCloud构建微服务——Hystrix实现容错及打印日志
  • 手把手教你优化小程序登录体验:一个按钮搞定微信手机号授权与后端Token处理
  • FlowState Lab 模型版本管理与回滚操作指南
  • 探索西门子S7 - 200PLC和MCGS6.2组态的楼宇温度与空调运行控制系统
  • 基于Hunyuan-MT-7B的运维文档多语言自动化系统
  • XPLDevices:面向X-Plane硬件开发的嵌入式固件框架
  • 从SORT到BoT-SORT:一文读懂多目标跟踪MOT算法这十年的“内卷”与进化
  • AI手势识别创意应用:零代码实现彩虹骨骼音乐交互
  • ROS2导航实战:用slam_toolbox+TurtleBot3从零搭建室内地图(附避坑指南)
  • 告别yum默认版本!在CentOS7上手动安装最新版LibreOffice 6.0.5的完整流程
  • PaddlePaddle-v3.3案例展示:低成本GPU实现高性能AI推理的真实效果
  • CEC2017测试集全攻略:如何用MATLAB一键运行12种算法并自动生成收敛曲线与评价报告
  • 绿联NAS部署aria2容器与Cloudreve离线下载的完整指南
  • 使用Qwen3进行自动化作业批改与反馈生成实践
  • OptiScaler终极指南:让任何显卡都能享受DLSS级画质增强的5步教程
  • Qwen3-TTS-12Hz-1.7B-CustomVoice在广播系统中的应用:自动化节目生成
  • 电动汽车充电负荷概率预测:条件扩散模型的奇妙之旅
  • S-5851A温度传感器Arduino驱动库深度解析
  • 别再“对不齐账”了:云原生时代的数据一致性,本质是工程能力的较量