zoukankan      html  css  js  c++  java
  • MVC项目中DateTime字段Json格式化输出的几种解决方案

      现在很多的项目都在使用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
        }
    View Code

      这是封装的一个扩展方法,使用比较简单,但是不够灵活,比如某些时间我们需要显示年月日时分秒,但有的时候只显示年月日,这就不好控制了。

      使用方法如下:

            public string Get()
            {
                return new { Time = DateTime.Now }.ToJson();
            }
    
            public ContentResult Get()
            {
                return Content(new { Time = DateTime.Now }.ToJson());
            }
            //这两种方法发生使用的时候存在特殊环境下js识别不了,认为是字符串的问题
    View Code

      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 } };
            }
    View Code

      以上两种方法我个人都不推荐使用!下面推荐第三种方法给大家使用:

      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种方法,当然只是针对后端输出的方法,前端的朋友怎么处理,方法应该有很多种吧!大家谁便百度一下一大堆啦!

      最后感谢大家阅读我的博客,才刚开始写博客,可能内容有点啰嗦,文笔有点不好,错别字还有点多!请大家多多理解包含,也希望大家多多发言,有什么意见尽管提!谢谢大家阅读!

      

  • 相关阅读:
    vue 客户端渲染和服务端渲染
    js 数组对象深拷贝
    vue template标签
    vue watch的高级用法
    js对象数组去重
    移动端触发touchend后阻止click事件
    重读JS(四)数据类型、作用域和内存问题
    重读JS(三)基本概念
    vue项目
    [vue问题解决]vue <router-link>在浏览器上点击失效(路由不跳转)
  • 原文地址:https://www.cnblogs.com/dukk/p/7569642.html
Copyright © 2011-2022 走看看