ASP.NET MVC JsonResult日期格式

时间:2009-04-07 15:27:06

标签: javascript asp.net-mvc json

我有一个控制器动作,它可以有效地简单地返回我模型的JsonResult。所以,在我的方法中,我有以下内容:

return new JsonResult(myModel);

除了一个问题外,这很有效。模型中有一个日期属性,它似乎在Json结果中返回,如下所示:

"\/Date(1239018869048)\/"

我应该如何处理日期,以便按我要求的格式退回?或者如何在脚本中处理上述格式?

25 个答案:

答案 0 :(得分:183)

只需展开casperOne's answer

JSON spec未考虑日期值。 MS必须进行调用,他们选择的路径是在字符串的javascript表示中利用一个小技巧:字符串文字“/”与“\ /”相同,字符串文字将从不< / em>被序列化为“\ /”(甚至“\ /”必须映射到“\\ /”)。

有关更好的解释,请参阅http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2(向下滚动到“从JavaScript文字到JSON”)

  

JSON的痛点之一是   缺少日期/时间字面。许多   人们感到惊讶和失望   他们第一次学习这个   遇到JSON。简单的解释   (安慰与否)缺席   日期/时间字面值是JavaScript   从来没有过:支持   JavaScript中的日期和时间值是   完全通过日期提供   宾语。大多数应用程序使用JSON   因此,通常作为数据格式   倾向于使用字符串或   数字来表示日期和时间   值。如果使用了字符串,则可以   通常期望它在ISO中   8601格式。如果使用数字,   相反,那么价值通常是   采取意味着数量   Universal Coordinated中的毫秒数   自纪元以来的时间(UTC),其中纪元是   定义为1970年1月1日午夜   (世界标准时间)。再一次,这仅仅是一个   约定而不是JSON的一部分   标准。如果您正在交换数据   与另一个应用程序,你会   需要查看其文档才能看到   它如何编码日期和时间值   在JSON文字中。例如,   微软的ASP.NET AJAX既不使用也不使用   描述的惯例。相反,   它将.NET DateTime值编码为   JSON字符串,其中的内容   string是/ Date(ticks)/和where   ticks表示自那以后的毫秒数   时代(UTC)。所以1989年11月29日,   4:55:30 AM,UTC编码为   “\ /日期(628318530718)\ /”。

解决方案就是解析它:

value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10));

但是我听说有一个设置可以让序列化程序使用DateTime语法输出new Date(xxx)个对象。我会试着去挖掘它。


JSON.parse()的第二个参数接受reviver函数,其中规定了返回之前最初生成的值的方式。

以下是日期的示例:

var parsed = JSON.parse(data, function(key, value) {
  if (typeof value === 'string') {
    var d = /\/Date\((\d*)\)\//.exec(value);
    return (d) ? new Date(+d[1]) : value;
  }
  return value;
});

请参阅JSON.parse()

的文档

答案 1 :(得分:94)

这是我在Javascript中的解决方案 - 非常像JPot,但更短(可能更快一点):

value = new Date(parseInt(value.substr(6)));

“value.substr(6)”取出“/ Date(”部分,而parseInt函数忽略最后出现的非数字字符。

编辑:我故意遗漏了基数(第二个参数为parseInt);见my comment below。此外,请注意ISO-8601日期比旧格式更受欢迎 - 因此这种格式通常不应用于新开发。请参阅优秀的Json.NET库,以获得使用ISO-8601格式序列化日期的绝佳替代方案。

对于ISO-8601格式的JSON日期,只需将字符串传递给Date构造函数:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

答案 2 :(得分:63)

处理客户端方面有很多答案,但如果需要,可以更改输出服务器端。

有几种方法可以解决这个问题,我将从基础开始。您必须继承JsonResult类并重写ExecuteResult方法。从那里你可以采取一些不同的方法来改变序列化。

方法1: 默认实现使用JsonScriptSerializer。如果您查看文档,可以使用RegisterConverters方法添加自定义JavaScriptConverters。但是有一些问题:JavaScriptConverter序列化为字典,即它需要一个对象并序列化为Json字典。为了使对象序列化为字符串,需要一些hackery,请参阅post。这个特殊的黑客也会逃脱字符串。

public class CustomJsonResult : JsonResult
{
    private const string _dateFormat = "yyyy-MM-dd HH:mm:ss";

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        HttpResponseBase response = context.HttpContext.Response;

        if (!String.IsNullOrEmpty(ContentType))
        {
            response.ContentType = ContentType;
        }
        else
        {
            response.ContentType = "application/json";
        }
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data != null)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            // Use your custom JavaScriptConverter subclass here.
            serializer.RegisterConverters(new JavascriptConverter[] { new CustomConverter });

            response.Write(serializer.Serialize(Data));
        }
    }
}

方法2(推荐): 第二种方法是从重写的JsonResult开始,然后使用另一个Json序列化器,在我的例子中是Json.NET序列化器。这不需要方法1的hackery。这是我对JsonResult子类的实现:

public class CustomJsonResult : JsonResult
{
    private const string _dateFormat = "yyyy-MM-dd HH:mm:ss";

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        HttpResponseBase response = context.HttpContext.Response;

        if (!String.IsNullOrEmpty(ContentType))
        {
            response.ContentType = ContentType;
        }
        else
        {
            response.ContentType = "application/json";
        }
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data != null)
        {
            // Using Json.NET serializer
            var isoConvert = new IsoDateTimeConverter();
            isoConvert.DateTimeFormat = _dateFormat;
            response.Write(JsonConvert.SerializeObject(Data, isoConvert));
        }
    }
}

用法示例:

[HttpGet]
public ActionResult Index() {
    return new CustomJsonResult { Data = new { users=db.Users.ToList(); } };
}

额外学分: James Newton-King

答案 3 :(得分:29)

Moment.js是一个广泛的日期时间库,也支持此功能。 http://momentjs.com/docs/#/parsing/asp-net-json-dates/

ex:moment(“/ Date(1198908717056-0700)/”)

这可能会有所帮助。 plunker output

答案 4 :(得分:19)

使用jQuery自动转换$.parseJSON

的日期
  

注意 :此答案提供了一个jQuery扩展,可添加自动ISO和.net日期格式支持。

由于您使用的是Asp.net MVC,我怀疑您在客户端使用jQuery。我建议您阅读this blog post,其代码如何使用$.parseJSON自动为您转换日期。

代码支持Asp.net格式的日期,如您提到的日期以及ISO格式的日期。所有日期都将使用$.parseJSON()自动为您格式化。

答案 5 :(得分:17)

我发现创建一个新的JsonResult并返回不满意 - 必须将return Json(obj)的所有来电替换为return new MyJsonResult { Data = obj },这很痛苦。


所以我想,为什么不使用JsonResult劫持ActionFilter

public class JsonNetFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is JsonResult == false)
        {
            return;
        }

        filterContext.Result = new JsonNetResult(
            (JsonResult)filterContext.Result);
    }

    private class JsonNetResult : JsonResult
    {
        public JsonNetResult(JsonResult jsonResult)
        {
            this.ContentEncoding = jsonResult.ContentEncoding;
            this.ContentType = jsonResult.ContentType;
            this.Data = jsonResult.Data;
            this.JsonRequestBehavior = jsonResult.JsonRequestBehavior;
            this.MaxJsonLength = jsonResult.MaxJsonLength;
            this.RecursionLimit = jsonResult.RecursionLimit;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            var isMethodGet = string.Equals(
                context.HttpContext.Request.HttpMethod, 
                "GET", 
                StringComparison.OrdinalIgnoreCase);

            if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet
                && isMethodGet)
            {
                throw new InvalidOperationException(
                    "GET not allowed! Change JsonRequestBehavior to AllowGet.");
            }

            var response = context.HttpContext.Response;

            response.ContentType = string.IsNullOrEmpty(this.ContentType) 
                ? "application/json" 
                : this.ContentType;

            if (this.ContentEncoding != null)
            {
                response.ContentEncoding = this.ContentEncoding;
            }

            if (this.Data != null)
            {
                response.Write(JsonConvert.SerializeObject(this.Data));
            }
        }
    }
}

这可以应用于任何返回JsonResult以使用JSON.Net的方法:

[JsonNetFilter]
public ActionResult GetJson()
{
    return Json(new { hello = new Date(2015, 03, 09) }, JsonRequestBehavior.AllowGet)
}

将以

回复
{"hello":"2015-03-09T00:00:00+00:00"}

根据需要!


如果您不介意在每个请求中调用is比较,可以将其添加到FilterConfig

// ...
filters.Add(new JsonNetFilterAttribute());

现在所有的JSON都将使用JSON.Net而不是内置的JavaScriptSerializer进行序列化。

答案 6 :(得分:11)

客户端和服务器之间的Ajax通信通常涉及JSON格式的数据。虽然JSON适用于字符串,数字和布尔值,但由于ASP.NET序列化它们的方式,它可能会给日期带来一些困难。由于它没有任何特殊的日期表示,因此它们被序列化为纯字符串。 作为一种解决方案,ASP.NET Web Forms和MVC的默认序列化机制以特殊形式序列化日期 - / Date(ticks)/ - 其中ticks是自1970年1月1日以来的毫秒数。

这个问题可以通过两种方式解决:

客户端

将收到的日期字符串转换为数字,并使用日期类的构造函数创建日期对象,并以ticks作为参数。

function ToJavaScriptDate(value) {
  var pattern = /Date\(([^)]+)\)/;
  var results = pattern.exec(value);
  var dt = new Date(parseFloat(results[1]));
  return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();

}

服务器端

之前的解决方案使用客户端脚本将日期转换为JavaScript Date对象。您还可以使用以您选择的格式序列化.NET DateTime实例的服务器端代码。 要完成此任务,您需要创建自己的ActionResult,然后按照您希望的方式序列化数据。

参考: http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html

答案 7 :(得分:7)

我有同样的问题,而不是返回实际的日期值,我刚刚使用了ToString(“dd MMM yyyy”)。然后在我的javascript中我使用了新的Date(datevalue),其中datevalue可能是“2009年1月1日”。

答案 8 :(得分:4)

见这个帖子:

http://forums.asp.net/p/1038457/1441866.aspx#1441866

基本上,虽然Date()格式是有效的javascript,但它不是有效的JSON(存在差异)。如果您想要旧格式,您可能必须自己创建一个外观并转换值,或者找到一种方法来获取JsonResult中类型的序列化器,并让它使用自定义格式的日期。

答案 9 :(得分:2)

我一直致力于解决这个问题,因为上述答案都没有真正帮助我。我正在使用jquery周日历,需要我的日期在服务器上和页面本地有时区信息。经过相当多的挖掘,我找到了一个可以帮助他人的解决方案。

我使用的是asp.net 3.5,vs 2008,asp.net MVC 2和jquery周历,

首先,我使用Steven Levithan编写的图书馆,帮助处理客户端的日期Steven Levithan's date library。 isoUtcDateTime格式非常适合我需要的格式。在我的jquery AJAX调用中,我使用带有isoUtcDateTime格式的库提供的格式函数,当ajax调用命中我的action方法时,datetime Kind设置为local并反映服务器时间。

当我通过AJAX向我的页面发送日期时,我通过使用“ddd,dd MMM yyyy HH':​​'mm':'ss'GMT'zzzz”格式化日期来将它们作为文本字符串发送。使用

可以轻松转换此格式的客户端
var myDate = new Date(myReceivedDate);

这是我的完整解决方案,减去Steve Levithan的来源,您可以下载:

控制器:

public class HomeController : Controller
{
    public const string DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz";

    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About()
    {
        return View();
    }


    public JsonResult GetData()
    {
        DateTime myDate = DateTime.Now.ToLocalTime();

        return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }

    public JsonResult ReceiveData(DateTime myDate)
    {
        return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }
}

使用Javascript:

<script type="text/javascript">

function getData() {
    $.ajax({
        url: "/Home/GetData",
        type: "POST",
        cache: "false",
        dataType: "json",
        success: function(data) {
            alert(data.myDate);
            var newDate = cleanDate(data.myDate);
            alert(newDate);
            sendData(newDate);
        }
    });
} 

function cleanDate(d) {
    if (typeof d == 'string') {
        return new Date(d) || Date.parse(d) || new Date(parseInt(d));
    }
    if (typeof d == 'number') {
        return new Date(d);
    }
    return d;
}

function sendData(newDate) {
    $.ajax({
        url: "/Home/ReceiveData",
        type: "POST",
        cache: "false",
        dataType: "json",
        data:
        {
            myDate: newDate.format("isoUtcDateTime")
        },
        success: function(data) {
            alert(data.myDate);
            var newDate = cleanDate(data.myDate);
            alert(newDate);
        }
    });
}

// bind myButton click event to call getData
$(document).ready(function() {
    $('input#myButton').bind('click', getData);
});
</script>

我希望这个快速示例可以帮助其他人处理我所处的相同情况。此时它似乎与Microsoft JSON序列化工作得很好,并且在时区之间保持我的日期正确。

答案 10 :(得分:2)

不是最优雅的方式,但这对我有用:

var ms = date.substring(6, date.length - 2);
var newDate = formatDate(ms);


function formatDate(ms) {

    var date = new Date(parseInt(ms));
    var hour = date.getHours();
    var mins = date.getMinutes() + '';
    var time = "AM";

    // find time 
    if (hour >= 12) {
        time = "PM";
    }
    // fix hours format
    if (hour > 12) {
        hour -= 12;
    }
    else if (hour == 0) {
        hour = 12;
    }
    // fix minutes format
    if (mins.length == 1) {
        mins = "0" + mins;
    }
    // return formatted date time string
    return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time;
}

答案 11 :(得分:2)

在knockoutjs中处理日期的更好方法是使用时刻库​​并处理像boss这样的日期。您可以轻松处理/ Date(-62135578800000)/等日期。无需为控制器中的序列化日期而烦恼。

function jsonToDate(date,format) {
   return moment(date).format(format);
}

一样使用它
var formattedDate = jsonToDate(date,'MM/DD/YYYY')

momentjs支持日期上的大量日期时间格式和实用程序功能。

答案 12 :(得分:1)

在查询中格式化日期。

var _myModel = from _m in model.ModelSearch(word)
    select new { date = ((DateTime)_m.Date).ToShortDateString() };

此解决方案的唯一问题是,如果任何日期值为空,则不会得到任何结果。为了解决这个问题,您可以在选择忽略日期空值的日期之前在查询中放置条件语句,或者您可以设置查询以获取所有结果,然后使用foreach循环遍历所有信息并分配值在进行SELECT新操作之前,所有日期都为空。

两者的例子:

var _test = from _t in adc.ItemSearchTest(word)
                        where _t.Date != null
                        select new { date = ((DateTime)_t.Date).ToShortDateString() };

第二个选项完全需要另一个查询,因此您可以为所有空值分配值。这个和foreach循环必须在您选择值的查询之前。

var _testA = from _t in adc.ItemSearchTest(word)
                         select _i;

            foreach (var detail in _testA)
            {
                if (detail.Date== null)
                {
                    detail.Date= Convert.ToDateTime("1/1/0001");
                }
            }

我发现的一个想法比所有的javascript示例都容易。

答案 13 :(得分:1)

您可以使用此方法:

String.prototype.jsonToDate = function(){
    try{
        var date;
        eval(("date = new " + this).replace(/\//g,''));
        return date;
    } 
    catch(e){
        return new Date(0);
    }
};

答案 14 :(得分:0)

我遇到了一些有关JSON日期的问题,因此决定通过解决SQL中的日期问题来解决该问题。将日期格式更改为字符串格式

select flddate from tblName

select flddate, convert(varchar(12), flddate, 113) as fldDateStr from tblName

通过使用fldDateStr,问题消失了,我仍然可以将date字段用于排序或其他目的。

答案 15 :(得分:0)

我发现这是更改服务器端最简单的方法。

using System.Collections.Generic;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

namespace Website
{
    /// <summary>
    /// This is like MVC5's JsonResult but it uses CamelCase and date formatting.
    /// </summary>
    public class MyJsonResult : ContentResult
    {
        private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Converters = new List<JsonConverter> { new StringEnumConverter() }
        };

        public FindersJsonResult(object obj)
        {
            this.Content = JsonConvert.SerializeObject(obj, Settings);
            this.ContentType = "application/json";
        }
    }
}

答案 16 :(得分:0)

烦人,不是吗?

我的解决方案是更改我的WCF服务,使其以更易读(非Microsoft)格式返回DateTimes。请注意下面的&#34; UpdateDateOriginal&#34;,这是WCF的默认日期格式,以及我的&#34; UpdateDate&#34;,其格式为更具可读性的东西。

enter image description here

以下是如何操作:

Changing WCF date format

希望这有帮助。

答案 17 :(得分:0)

重写控制器Json / JsonResult以返回JSON.Net:

This works a treat

答案 18 :(得分:0)

0

在您的cshtml中,

<tr ng-repeat="value in Results">                
 <td>{{value.FileReceivedOn | mydate | date : 'dd-MM-yyyy'}} </td>
</tr>

在您的JS文件中,也许是app.js,

在app.controller之外,添加以下过滤器。

这里,“ mydate”是您用来解析日期的函数。这里的“ app”是包含angular.module的变量

app.filter("mydate", function () {
    var re = /\/Date\(([0-9]*)\)\//;
    return function (x) {
        var m = x.match(re);
        if (m) return new Date(parseInt(m[1]));
        else return null;
    };
});

答案 19 :(得分:0)

对我有用的是创建一个包含date属性作为字符串的viewmodel。从域模型中分配DateTime属性,并在将值分配给viewmodel时调用date属性上的.ToString()。

MVC操作方法的JSON结果将以与视图兼容的格式返回日期。

查看模型

public class TransactionsViewModel
{
    public string DateInitiated { get; set; }
    public string DateCompleted { get; set; }
}

域模型

public class Transaction{
   public DateTime? DateInitiated {get; set;}
   public DateTime? DateCompleted {get; set;}
}

控制器操作方法

public JsonResult GetTransactions(){

var transactions = _transactionsRepository.All;
        var model = new List<TransactionsViewModel>();

        foreach (var transaction in transactions)
        {
            var item = new TransactionsViewModel
            {
                ...............
                DateInitiated = transaction.DateInitiated.ToString(),
                DateCompleted = transaction.DateCompleted.ToString(),
            };

            model.Add(item);
        }
        return Json(model, JsonRequestBehavior.AllowGet);
}

答案 20 :(得分:0)

不是没有,但还有另一种方式。首先,构建您的LINQ查询。然后,构造一个Enumerated结果的查询,并为您应用任何类型的格式化工作。

var query = from t in db.Table select new { t.DateField };
var result = from c in query.AsEnumerable() select new { c.DateField.toString("dd MMM yyy") };

我不得不说,额外的步骤令人讨厌,但效果很好。

答案 21 :(得分:0)

这是我编写的一些JavaScript代码,它从ASP.NET MVC传递的日期设置<input type="date">值。

    var setDate = function (id, d) {
    if (d !== undefined && d !== null) {
        var date = new Date(parseInt(d.replace("/Date(", "").replace(")/", ""), 10));
        var day = ('0' + date.getDate()).slice(-2);
        var month = ('0' + (date.getMonth() + 1)).slice(-2);
        var parsedDate = date.getFullYear() + "-" + (month) + "-" + (day);
        $(id).val(parsedDate);
    }
};

您可以这样调用此函数:

setDate('#productCommissionStartDate', data.commissionStartDate);

其中,CommissionStartDate是MVC传递的JSON日期。

答案 22 :(得分:0)

它返回服务器日期格式。您需要定义自己的功能。

function jsonDateFormat(jsonDate) {

// Changed data format;
return (new Date(parseInt(jsonDate.substr(6)))).format("mm-dd-yyyy / h:MM tt");

};

答案 23 :(得分:0)

在您的页面中添加jquery ui插件。

function JsonDateFormate(dateFormate, jsonDateTime) {
    return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1)));
};

答案 24 :(得分:-1)

最简单的一个:

var milisegundos = parseInt(data.replace(“/ Date(”,“”).replace(“)/”,“”));
Var newDate = new Date(milisegundos)。 toLocaleDateString (“en-UE”);