16

我有一个使用 JSON 数据调用 MVC 控制器的 javascript 函数:

var specsAsJson = JSON.stringify(specs);
$.post('/Home/Save', { jsonData: specsAsJson });

在服务器端,在控制器内,我似乎无法克服这个错误:

/Date(1347992529530)/ 不是 DateTime 的有效值。

当我调用 Deserialize() 时发生该异常(下面方法中的第三行):

    public ActionResult Save(string jsonData)
    {
        var serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new[] { new TimeSpanJsonConverter() });
        var specs = serializer.Deserialize<List<EquipmentSpecWithParameterlessConstructor>>(jsonData);

        return View("Index", _allTrackerJobs);
    }

我一直在做一些谷歌搜索,上面的代码是我完成这项工作的最新尝试(使用此处的 TimeSpanJsonConverter )。其他方法显示仅向服务器发送日期,但我有一个将日期作为某些属性的对象列表。

是否有一种优雅的、普遍接受的方法来解决这个问题,还是我们仍然需要某种丑陋的解决方法?解决这个问题的正确方法是什么?

=================== 原始问题结束===================


编辑 - 通过使用 JsonConvert 序列化解决

请参阅下面的答案(不是这个问题中糟糕的解决方法)。


编辑 - 糟糕的解决方法

我创建了一个具有与域对象完全相同的字段的 DTO,除了我创建了日期字段字符串以便它们可以反序列化。现在我可以反序列化它,我将努力将日期转换为有效格式,以便我可以从我的 DTO 创建域对象。

public class EquipmentSpecDto
{
    public string StartTime { get; set; }
    public string EndTime { get; set; }
    // more properties here
}

我只是使用 DTO 进行反序列化:

var specs = serializer.Deserialize<List<EquipmentSpecDto>>(jsonData);

编辑 2 - 将 JavaScript 日期转换为 .NET

为了完整起见,并希望我为别人节省一个小时,这就是我能够转换 javascript 日期的方式:

    foreach (EquipmentSpecDto specDto in specDtos)
    {
        // JavaScript uses the unix epoch of 1/1/1970. Note, it's important to call ToLocalTime()
        // after doing the time conversion, otherwise we'd have to deal with daylight savings hooey.
        DateTime unixEpoch       = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        Double startMilliseconds = Convert.ToDouble(specDto.StartTime.Substring(6, 13));
        Double endMilliseconds   = Convert.ToDouble(specDto.EndTime.Substring(6, 13));
        DateTime startTime       = unixEpoch.AddMilliseconds(startMilliseconds).ToLocalTime();
        DateTime endTime         = unixEpoch.AddMilliseconds(endMilliseconds).ToLocalTime();
        EquipmentSpec spec       = new EquipmentSpec(startTime, endTime, specDto.Equipment);

        specs.Add(spec);
    }
4

6 回答 6

13

I found a simple answer. In my javascript, I was serializing the data using the JavaScriptSerializer. After much googling, I found this article that shows how to serialize using JsonConvert that causes a more .NET-friendly DateTime to be used.

Old:

var specs = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(ViewBag.JobSpecEquipment))

Dates look like this: Date(1348017917565)

New:

var specs = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.JobSpecEquipment));

Dates look like this: 2012-09-18T21:27:31.1285861-04:00

So the problem was really how I was serializing in the first place. Once I used JsonConvert, deserialization on the back end simply worked.

于 2012-09-19T01:29:52.693 回答
7

我在互联网上找到了这段代码。它对我来说就像一个魅力......

function customJSONstringify(obj) {
    return JSON.stringify(obj).replace(/\/Date/g, "\\\/Date").replace(/\)\//g, "\)\\\/")
}
于 2014-02-18T21:19:06.537 回答
4

在 Javascript 日期和各种服务器端语言之间转换时经常引起人们注意的一件事是,尽管双方可能能够理解 unix 样式的时间戳值,但 JS 使用微秒精度的时间戳,而在大多数其他语言中,默认值时间戳精度是秒。

换句话说,Javascript 中的 1347993132851 需要除以 1000 才能在其他语言中被识别为 unix 时间戳。

或者,如果您的平台可以接受格式化的日期字符串,请使用 JavascriptDate()对象将时间戳值转换为格式化的日期以发送到服务器。或者更好的是,使用Date.jsMoment.js等辅助库。

于 2012-09-18T21:34:12.327 回答
2

JavaScript(嗯,EcmaScript)基于 ISO-8601 标准的简化定义了它的 DateTime 字符串交换格式。

XML Schema 也基于 ISO-8601 定义了它的 DateTime 字符串交换格式。

我发现使用 .NET 类System.Runtime.Remoting.Metadata.W3cXsd2001.SoapDateTime来处理从 .NET DateTime 值到 XML 格式的转换很方便。

由于 JavaScript 基于相同的 ISO-8601 标准,也许它也适用于您的 JSON 案例。

于 2012-09-18T21:31:19.870 回答
2

我接受了@Bob Horn 的回答,但它对我不起作用。我的 REST 服务正在使用 Javascritpt 日期。我将引用的答案改编为扩展方法。


using System;

namespace Mediatel.Framework
{
    public static class JsonDate
    {
        public static DateTime ConvertToDateTime(this string jsonDate)
        {
            // JavaScript uses the unix epoch of 1/1/1970. Note, it's important to call ToLocalTime()
            // after doing the time conversion, otherwise we'd have to deal with daylight savings hooey.
            DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            Double milliseconds = Convert.ToDouble(jsonDate);
            DateTime dateTime = unixEpoch.AddMilliseconds(milliseconds).ToLocalTime();

            return dateTime;
        }
    }
}
于 2017-02-14T17:00:19.340 回答
1

收到错误后

/Date(1347992529530)/ 不是 DateTime 的有效值。

使用此替换对我有用。

var data = ko.toJSON({ objext: obj});
$.ajax({
    url: "/API/API.asmx/SaveObject",
    type: "POST",
    dataType: "json",
    contentType: "application/json; char-utf8;",
    data: data.replace(/\/Date/g, "\\\/Date").replace(/\)\//g, "\)\\\/"),
    success: function (r) {},
    error: function (e) {},
    complete: function () {}
});
于 2018-09-05T11:48:38.703 回答