前言
项目开发中不管是前台还是后台都会遇到烦人的null,数据库表中字段允许空值,则代码实体类中对应的字段类型为可空类型Nullable<>,如int"htmlcode">
public void ConfigureServices(IServiceCollection services) { //配置Mvc + json 序列化 services.AddMvc() .AddNewtonsoftJson(options => { //数据格式首字母小写 不使用驼峰 小驼峰firstName 大驼峰 FirstName options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); //使用默认方式,不更改元数据的key的大小写 //options.SerializerSettings.ContractResolver = new DefaultContractResolver(); // 忽略循环引用 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 设置时间格式 options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; //忽略空值 不包含属性的null序列化 //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; //忽略默认值和null 1、不包含属性默认值和null //options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Igno }) }
1、空值的处理
序列化和反序列化时需要忽略值为null的属性,设置SerializerSettings.NullValueHandling的值
- NullValueHandling.Ignore 序列化和反序列化对象时忽略空值。
- NullValueHandling.Include 序列化和反序列化对象时包含空值。
2、默认值的处理
序列化和反序列化时需要忽略默认值属性,设置SerializerSettings.DefaultValueHandling的值
- DefaultValueHandling.Ignore 序列化和反序列化时忽略默认值
- DefaultValueHandling.Include序列化和反序列化时包含默认值
3、示例代码
/*包含属性的默认值与null序列化*/ { "Name": null, "Age": 0, "Partner": null, "Salary": 0.0 } /*不包含属性的默认值序列化*/ { "Name": "Hello World", "Age": 28 } /*不包含属性的null序列化*/ { "Name": "Hello World", "Age": 28, "Salary": 0.0 }
通过上面的分析:一种是不包含属性的默认值序列化,另一种是不包含属性的null序列化,都不能满足目前的需求接口统一返回的null序列化为空。
二、解决问题
1、项目WebAPI默认返回的JSON结果格式如下:
{ "code": 0, "msg": "查询成功", "data": { "id": 1, "title": "炎炎夏日暖暖肚", "describe": "", "author": null, "authorId": null, "linkSource": null, "author_Picture": null, "content": "炎炎夏日,很多人喜欢吃些寒凉的食物解暑,可这种做法非常伤身。", } }
2、需要解决的问题把所有的null替换为空,具体如下图所示:
3、解决方案
需要自己写一个NullToEmptyStringResolver类,然后重写CamelCasePropertyNamesContractResolver,但是该方法只能解决string类型null→""的问题,对其他可空类型无效,比如:int"htmlcode">
public class NullToEmptyStringResolver : CamelCasePropertyNamesContractResolver { /// <summary> /// 创建属性 /// </summary> /// <param name="type">类型</param> /// <param name="memberSerialization">序列化成员</param> /// <returns></returns> protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { return type.GetProperties().Select(c => { var jsonProperty = base.CreateProperty(c, memberSerialization); jsonProperty.ValueProvider = new NullToEmptyStringValueProvider(c); return jsonProperty; }).ToList(); } } public class NullToEmptyStringValueProvider : IValueProvider { private readonly PropertyInfo _memberInfo; /// <summary> /// 构造函数 /// </summary> /// <param name="memberInfo"></param> public NullToEmptyStringValueProvider(PropertyInfo memberInfo) { _memberInfo = memberInfo; } /// <summary> /// 获取Value /// </summary> /// <param name="target"></param> /// <returns></returns> public object GetValue(object target) { var result = _memberInfo.GetValue(target); if (_memberInfo.PropertyType == typeof(string) && result == null) result = string.Empty; return result; } /// <summary> /// 设置Value /// </summary> /// <param name="target"></param> /// <param name="value"></param> public void SetValue(object target, object value) { _memberInfo.SetValue(target, value); } }
在Startup.cs代码里面修改,标记为红色的代码,如下所示:
//配置MVC+JSON序列化 services .AddMvc(options =>{options.EnableEndpointRouting = false;}) .AddNewtonsoftJson(options => { //使用默认方式,不更改元数据的key的大小写 //options.SerializerSettings.ContractResolver = new DefaultContractResolver(); //数据格式首字母小写 不使用驼峰 小驼峰firstName 大驼峰 FirstName //options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); options.SerializerSettings.ContractResolver = new NullToEmptyStringResolver(); // 忽略循环引用 options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 设置时间格式 options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss"; //忽略空值 不包含属性的null序列化 //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore; //忽略默认值和null 1、不包含属性默认值和null //options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Igno })
修改完配置,重新运行完成,实现null替换为空的效果,运行结果如下所示:
{ "code": 0, "msg": "查询成功!", "data": { "id": 1, "title": "炎炎夏日暖暖肚", "describe": "", "author": "", "authorId": "", "linkSource": "", "author_Picture": "", "source": 0, "content": "炎炎夏日,很多人喜欢吃些寒凉的食物解暑,可这种做法非常伤身。" } }
三、总结
.NET Core下Newtonsoft.Json序列化时字符串null替换成空,通过ContractResolver类为属性添加一些序列化设置、自定义属性名、设置时间格式、有选择性的序列化属性等,实现WebAPI返回JSON格式统一化。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。