王朝网络
分享
 
 
 

JSON.NET 使用技巧

王朝学院·作者佚名  2016-05-20  
宽屏版  字体: |||超大  

JSON.NET 使用技巧1. 序列化相关技巧通过特性忽略某些属性

有时候我们会有这样的需求,我们只需要序列化实体类中的一部分属性,这时候我们可以通过声明忽略掉一些我们不需要序列化的属性,有两种方式可以使用么达到这个目标:

首先,可以考虑使用JsonIgnore特性修饰不需要进行序列化的属性,如下所示:

public class EmployeeBean{ public Guid Id { get; set; } public string Name { get; set; } public string Email { get; set; } public decimal Salary { get; set; } public string Phone { get; set; } [JsonIgnore] public DateTime HireDate { get; set; }}

运行程序:

var employeeBean = new EmployeeBean(){ Id = Guid.NewGuid(), Name = "gyzhao", Email = "gyzhao@gyzhao.com", Salary = 10000, Phone = "13912390987", HireDate = new DateTime(2012, 2, 1)}; var jsonString = JsonConvert.SerializeObject(employeeBean, Formatting.Indented);//输出://{// "Id": "69a406ad-902c-45d3-8ba7-89a09779ed52",// "Name": "gyzhao",// "Email": "gyzhao@gyzhao.com",// "Salary": 10000.0,// "Phone": "13912390987"//}

如果说你需要序列化的类有很多的属性,而你是需要使用其中的一小部分,如果使用上面的上面方式就会比较繁琐(因为需要忽略的属性太多了),这时候可以考虑使用DataContract特性修饰被序列化的类,使用DataMember特性修饰需要进行序列化的属性,其他没有该特性属性会被自动忽略掉。如下所示:

[DataContract]public class EmployeeBean{ [DataMember] public Guid Id { get; set; } [DataMember] public string Name { get; set; } [DataMember] public string Email { get; set; } [DataMember] public decimal Salary { get; set; } public string Phone { get; set; } public DateTime? HireDate { get; set; }}

运行程序:

var employeeBean = new EmployeeBean(){ Id = Guid.NewGuid(), Name = "gyzhao", Email = "gyzhao@gyzhao.com", Salary = 10000, Phone = "13912390987", HireDate = new DateTime(2012, 2, 1)}; var jsonString = JsonConvert.SerializeObject(employeeBean, Formatting.Indented);//输出://{// "Id": "69a406ad-902c-45d3-8ba7-89a09779ed52",// "Name": "gyzhao",// "Email": "gyzhao@gyzhao.com",// "Salary": 10000.0//}

DataContract特性和DataMember特性都从属于: System.Runtime.Serialization命名空间。

动态序列化对象属性

多谢园友 @夜色、花清浅 的提醒,确实有这样的场景:更多的我们可能需要的是动态的来确定需要序列化哪些属性,比如对于EmployeeBean来说:A方法需要序列化 Name 和 Id 属性,而 B方法需要序列化 Email 和 Phone 属性,在这种情况下,前面的两种使用特性的方式并不能很好的适应需求的变化,通过查询 JSON.NET 的文档(传送门:Json.NET Documentation),官方文档提供了这个API的示例程序,下面是改进的示例:

var employeeBean = new EmployeeBean(){ Id = Guid.NewGuid(), Name = "gyzhao", Email = "gyzhao@gyzhao.com", Salary = 10000, Phone = "13912390987", HireDate = new DateTime(2015, 5, 4)};var perperties = new List<string>(){ employeeBean.GetPRopertyName(t => t.Email), employeeBean.GetPropertyName(t => t.Phone)};var jsonString = JsonConvert.SerializeObject(employeeBean, Formatting.Indented, new JsonSerializerSettings(){ ContractResolver = new JsonDynamicContractResolver(perperties) });//{// "Email": "gyzhao@gyzhao.com",// "Phone": "13912390987"//}Console.WriteLine(jsonString);

下面是定义 JsonDynamicContractResolver 类的定义:

public class JsonDynamicContractResolver : DefaultContractResolver{ private readonly List<string> _propertiesList; public JsonDynamicContractResolver(IEnumerable<string> propertiesEnumerable) { if (propertiesEnumerable != null) { _propertiesList = propertiesEnumerable.ToList(); } } protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization); //只序列化构造器中传入的包含在字符串中的属性 if (_propertiesList != null && _propertiesList.Any()) { properties = properties.Where(p => _propertiesList.Exists(pString => pString == p.PropertyName)).ToList(); } return properties; }}

在 传入 JsonDynamicContractResolver 构造函数中的指定序列化属性的集合时,我在这里使用了扩展方法:GetPropertyName ,这个方法通过传入一个 Lambda 表达式来获取需要序列化属性的字符串表示,这里是通过表达式树来实现的。相对于直接硬编码属性名称的字符串来说,使用表达式树动态获取在效率上有所损失(可接受的程度),不过换取的是设计上的灵活。比如:当我们更改属性名称时,编译器可以为我们提供类型安全的保护。而如果硬编码的话,如果一旦忘记修改,那么运行就会抛出异常,特别是系统中如果有很多地方都是用这种硬编码方式的话,那么维护起来就是一个噩梦了。下面是该扩展方法的代码:

public static class Extensions{ /// <summary> /// 获取对象实例属性的字符串表示 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <param name="func"></param> /// <returns></returns> public static string GetPropertyName<T>(this T obj, Expression<Func<T, object>> func) { var propertyName = string.Empty; var expression = func.Body as UnaryExpression; if (expression != null) { propertyName = ((MemberExpression) expression.Operand).Member.Name; } else { var memberExpression = func.Body as MemberExpression; if (memberExpression != null) { propertyName = memberExpression.Member.Name; } else { var body = func.Body as ParameterExpression; if (body != null) { propertyName = body.Type.Name; } } } return propertyName; }}

序列化对象时循环引用异常的解决办法

序列化一个对象时,如果该对象有一个集合属性,改集合的类型就是对象本身的话,默认序列化的方法会报一个循环引用的异常,如果需要序列化,只需声明下面的属性即可:

JsonConvert.SerializeObject(result,new JsonSerializerSettings{ReferenceLoopHandling=ReferenceLoopHandling.Serialize})

2. 反序列化相关技巧2.1 使用匿名类型作为反序列化实体

var jsonString = @"{ 'Id': '69a406ad-902c-45d3-8ba7-89a09779ed52', 'Name': 'gyzhao', 'Salary': 10000.0, 'HireDate': '2012-02-01T00:00:00' }";var employee = new { Name = default(string), Salary = default(decimal), HireDate = default(DateTime), Id = default(Guid) };var employeeBean = JsonConvert.DeserializeAnonymousType(jsonString, employee);

3. 创建JSON//命令式的创建JSON对象var array = new JArray();var text = new JValue("Manual text");var date = new JValue(DateTime.Now);array.Add(text);array.Add(date);Console.WriteLine(array.ToString());//使用声明式的语法var rss = new JObject( new JProperty("channel", new JObject( new JProperty("title", "James Nexton-king"), new JProperty("link", "http://james.newtonking.com"), new JProperty("description", "James Newton-Kin's blog."), new JProperty("item", "BB"))));Console.WriteLine(rss.ToString());//通过一个匿名对象创建JSONJObject o = JObject.FromObject(new{ channel = new { title = "James Newton-king", link = "http://james.netwoing.com", item = new List<string>() { "A", "B", "C", "D", "E" } }});Console.WriteLine(o.ToString());

参考&进一步阅读http://www.newtonsoft.com/json

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有