现在很多的项目都在使用MVC-EF,前段使用vue angularjs 等框架,在使用的过程中,大家可能都出现过一个问题,就是后端返回的JSON数据,关于DateTime字段JSON成了"/Date(20130450000365)"这种形式,这样对于页面呈现使用带来了很大的麻烦,聪明点的同学可能会拿去拆分字符串,取出中间的时间戳进行转换,然后又实用js进行格式化.....
从上面的步骤来看,这个过程并不简单,甚至繁琐。依我个人的说法就是:是不好用,麻烦,不能普罗大众。哪有没有好的办法呢?下面我就为大家介绍下其他办法
1.自己封装一个方法,自己设置其中的时间转换规则,下面是代码
public static class JsonHelper { private static JsonSerializerSettings _jsonSettings; #region init static JsonHelper() { IsoDateTimeConverter datetimeConverter = new IsoDateTimeConverter(); datetimeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; _jsonSettings = new JsonSerializerSettings(); _jsonSettings.MissingMemberHandling = MissingMemberHandling.Ignore; _jsonSettings.NullValueHandling = NullValueHandling.Ignore; _jsonSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; _jsonSettings.Converters.Add(datetimeConverter); } #endregion #region 将指定的对象序列化成 JSON 数据。 /// <summary> /// 将指定的对象序列化成 JSON 数据。 /// </summary> /// <param name="obj">要序列化的对象。</param> /// <returns></returns> public static string ToJson(this object obj) { try { if (null == obj) return null; return JsonConvert.SerializeObject(obj, Formatting.None, _jsonSettings); } catch (Exception ex) { throw new Exception("Json序列化出错:" + ex.Message); } } #endregion #region 将指定的 JSON 数据反序列化成指定对象。 /// <summary> /// 将指定的 JSON 数据反序列化成指定对象。 /// </summary> /// <typeparam name="T">对象类型。</typeparam> /// <param name="json">JSON 数据。</param> /// <returns></returns> public static T FromJson<T>(this string json) { try { return JsonConvert.DeserializeObject<T>(json, _jsonSettings); } catch (Exception ex) { throw new Exception("Json反序列化出错:" + ex.Message); } } #endregion }
这是封装的一个扩展方法,使用比较简单,但是不够灵活,比如某些时间我们需要显示年月日时分秒,但有的时候只显示年月日,这就不好控制了。
使用方法如下:
public string Get() { return new { Time = DateTime.Now }.ToJson(); } public ContentResult Get() { return Content(new { Time = DateTime.Now }.ToJson()); } //这两种方法发生使用的时候存在特殊环境下js识别不了,认为是字符串的问题
2.控制器直接返回object的形式
public object Get() { return new { Time = DateTime.Now }; }
这种方法使用起来比上面更简单,但是问题更大,它不能解析List类型,比如
//能正常解析 public object Get() { return new { Childe = new { Time = DateTime.Now } }; } //不能正常解析 //页面解析结果为:System.Collections.Generic.List`1[System.Object] public List<object> GetList() { return new List<object> { new { time = DateTime.Now } }; }
以上两种方法我个人都不推荐使用!下面推荐第三种方法给大家使用:
3.定义只读属性的方法,在项目中我们可以这么写:
public DateTime Time { get; set; } /// <summary> /// 不会映射到数据库,LastUpdateTime字段显示用 /// </summary> [NotMapped] public string ShowTime { get { return Time.ToString("yyyy-MM-dd"); } }
上面的代码是适用于EF的Model,同时也是适用于任何类对象,结构成语。上面代码中我写的NotMapped只是用于EF Model中,如果你不是EF Model请去掉
看到这里可能有部分同学会问了,如果使用的是数据库优先怎么处理?答案:使用部分类解决,请看以下代码:
public partial class ProjectHistory { /// <summary> /// 不会映射到数据库,LastUpdateTime字段显示用 /// </summary> [NotMapped] public string ShowTime { get { return Time.ToString("yyyy-MM-dd"); } } }
这种方法可以很好的解决第1个问题中不灵活的问题,如果这个字段有多种显示形式我可以编写多个只读属性解决
但是呢,这个方案还是存在一个问题,在ORM项目中,很多同学很多时候啊返回的是匿名类型,这时候就尴尬了。匿名类型查询数据库时不能对时间进行ToString()格式化(Linq不支持),必须查询出来再次创建匿名类型才能进行ToSring()格式化,这样看起来就很麻烦,但是输出格式却很灵活,这个可以配合其他方法一起使用,效果更好!
4.定义全局设置,这一种方法只适用于webapi的项目,在Global.asax中添加以下代码:
//清除所有的序列化化适配器 GlobalConfiguration.Configuration.Formatters.Clear(); //创建一个JSON序列化适配器 JsonMediaTypeFormatter format = new JsonMediaTypeFormatter(); //重新定义JSON时间序列化配置器 format.SerializerSettings.DateFormatString = "yy-MM-dd HH:mm:ss"; //注册JSON序列化适配器 GlobalConfiguration.Configuration.Formatters.Add(format);
这种方法只能正对WebApi 项目中的Api控制器,一样和方法1配置存在不灵活的问题,其实我认为MVC都应该支持这种定义的才对,但是我确实没找到如何定义普通控制器的方法,不知道有没有大神知道的?求回复
以上就是我个人想到的4种方法,当然只是针对后端输出的方法,前端的朋友怎么处理,方法应该有很多种吧!大家谁便百度一下一大堆啦!
最后感谢大家阅读我的博客,才刚开始写博客,可能内容有点啰嗦,文笔有点不好,错别字还有点多!请大家多多理解包含,也希望大家多多发言,有什么意见尽管提!谢谢大家阅读!