将字符串中的JSON日期替换为更易读的日期

10
我们希望向正在测试我们应用程序的用户展示一些JSON信息。因此,我们在ASP.NET的代码后台调用REST服务并返回一个字符串,其中包含许多JSON数据。
然后,我们将它放入页面中的PRE元素中,调用beautify以创建易读的JSON格式。虽然内容具有人类可读性,但有一个问题:所有日期都显示为普通的JSON格式,例如"/Date(1319266795390+0800)/"。
我想要做的是,在将字符串添加到PRE元素之前,将JSON中的这些日期替换为“常规”日期(即C#中的日期)。我考虑使用一些正则表达式,但是我无法弄清楚如何做到这一点...

1
你能否在问题的文本中包含更完整的JSON字符串示例,以便使其更易读?问题在于JSON主要用于将对象转换为字符串以便于传输到Web客户端,并将JSON转换回JavaScript对象。JavaScript对象不应该是可读的。例如,如果您有一个对象数组,其中一个属性是日期,则无法使其对人类更易读。因此,重要的是要了解您已将哪种数据(哪个对象)序列化为JSON字符串。 - Oleg
你会考虑使用 JavaScript 解决方案,还是坚持使用 C# 进行转换? - jamesmortensen
9个回答

15

我一直在处理JSON字符串中的日期,没有标准的方式来表示,这就是为什么有这么多不同的方法!或许最好的方式是在JSON规范中指定一个标准的日期格式!

微软采用自己的方式,计算从1970年以来的UTC格式的毫秒数,类似于"/Date(1319266795390+0800)/"

我们一直使用正则表达式将上述字符串转换为ISO-8601格式,这是一种W3C标准,易于阅读并且大多数浏览器将日期序列化为字符串的方式,具体如下:

static readonly long DATE1970_TICKS = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
static readonly Regex DATE_SERIALIZATION_REGEX = new Regex(@"\\/Date\((?<ticks>-?\d+)\)\\/", RegexOptions.Compiled);

static string ISO8601Serialization(string input)
{
    return DATE_SERIALIZATION_REGEX.Replace(input, match =>
    {
        var ticks = long.Parse(match.Groups["ticks"].Value) * 10000;
        return new DateTime(ticks + DATE1970_TICKS).ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss.fff");
    });
}

您可以轻松更改格式以满足您的需求,要查看自定义日期和时间格式,请查看此处的MSDN文章

以下是使用方法:

JavaScriptSerializer ser = new JavaScriptSerializer();
var JsonSrt = ISO8601Serialization(ser.Serialize(DateTime.Now));    // "\"2012-05-09T14:51:38.333\""

更新:

有一种替代方法可以使用正则表达式在JavaScript中调整从服务器返回的JSON字符串以使其更易读:

var str = "/Date(1319266795390+0800)/";
str.replace(/\/Date\((\d+)\+\d+\)\//, function (str, date) {
    return new Date(Number(date)).toString();
});

不错的解决方案。我们正在使用WCF框架,它会自动将对象转换为JSON。在代码中,我们只需返回一个带有datamember属性注释的POCO对象,当调用函数时,由于项目类型的性质,输出会被转换为JSON。我的意思是(据我所知),在代码中没有任何时刻/地点可以插入自定义数据替换代码。 - Michel
WCF使用DataContractJsonSerializer来序列化POCO/DataContract对象,可以调整默认的JSON序列化器,并将DataContractJsonSerializer替换为自定义的序列化器!这里有一篇文章向您展示如何做:http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx 无论如何,在上面的更新中,还有一种使用JavaScript中的正则表达式调整从服务器返回的JSON文本的方法。 - Kamyar Nazeri
这对于Date(##)非常有效,但对于Date(##+####)即不包含任何时区信息。 尝试在此字符串上执行此操作:“{"EndTime":"\/Date(1381479678557)\/","StartTime":"\/Date(1381479678557+0200)\/"}”。 它只替换了EndTime而没有替换StartTime。 - JensB

5
解决方案在问题所示的字符串中。JavaScript Date对象将解析该格式并生成可读版本,因此Date(1319266795390 +0800)返回“ Wed Apr 18 2012 08:13:22 GMT-0500(中部夏令时)”。
要从字符串中删除正斜杠,您可以使用replace函数和正则表达式:“/Date(1319266795390 +0800)/” replace(/ \ / g,“”)

啊,但我的字符串不仅包含那个日期,它还包含其他50个人的属性,其中有几个日期。 - Michel
米歇尔 - 正则表达式是为从非常长的字符串中检索特定数据而设计的。埃里克建议的方法应该适用于您,并且完全可以使用JavaScript完成。 - jamesmortensen

4
你可以使用这个:
string date = "/Date(1319266795390+0800)/";
string regex = @"/Date\((.*?)\+(.*?)\)/";
Match match = Regex.Match(date, regex);
DateTime d = new DateTime(1970, 01, 01).AddMilliseconds(long.Parse(match.Result("$1")));

2
假设您想要序列化的类如下所示:
public class Something
{
    public int ID;
    public string Name;
    public DateTime Date;
}

请将其更改为:

public class Something
    {
        public int ID;
        public string Name;
        public DateTime Date;
        public string HumanReadableDate { get { return Date.ToLongDateString(); } }
    }

或者,如果你想让这个额外的属性仅在测试环境中显示:

public class Something
    {
        public int ID;
        public string Name;
        public DateTime Date;
        #if DEBUG
        public string HumanReadableDate { get { return Date.ToLongDateString(); } }
        #endif
    }

此外,你可以使用.ToString("yyyy-MM-dd HH:mm")或任何其他格式,而不是.ToLongDateString()

1

使用类似于正则表达式的东西:

(?<= /Date\( ) 
  (?<ticks>[0-9]+)
  ((?<zonesign>[+-])
   (?<zonehour>[0-9]{2})
   (?<zoneminutes>[0-9]{2})
  )?
(?= \)/ )

这将匹配/Date(1319266795390+0800)/括号内的部分。然后,您可以调用Regex.Replace来替换数字为格式良好的DateTime

使用匹配评估委托中获得的Match对象并提取ticks、zonesign、zonehour和zoneminutes部分,将其转换为整数。

然后将javascript ticks转换为.NET ticks(应该是*10000),根据ticks构造.NET DateTime并添加/减去时区的小时和分钟。 将DateTime转换为字符串并将其作为替换返回。


1

1
如果您的JSON是.NET类的序列化表示形式,也许您可以使用在服务器上对其进行反序列化,或者如果您不需要处理多个数据集的通用解决方案,也许您只需为您的JSON对象定义一个存根类即可:
string json = "{\"Test\": \"This is the content\"}";
DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(TestJson));
var deserialisedContent = ds.ReadObject(new MemoryStream(Encoding.ASCII.GetBytes(json)));

foreach (var field in typeof (TestJson).GetFields())
{
    Console.WriteLine("{0}:{1}", field.Name, field.GetValue(deserialisedContent));
}

...

[DataContract]
private class TestJson
{
    [DataMember]
    public string Test;
}

1
创建一个字符串属性,例如出生日期(dateofbirth),并将您的日期时间变量返回为:
    public string DateOfBirthString
    {
        get { return DateOfBirth.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss"); }
        set { DateOfBirth = string.IsNullOrEmpty(value) ? new DateTime(1900, 1, 1) : Convert.ToDateTime(value); }
    }

因为这将返回字符串,所以在客户端也会保持一致,并且从用户获取字符串日期时间并进行转换。


0
string input = [yourjsonstring]; 
MatchEvaluator me = new MatchEvaluator(MTListServicePage.MatchDate);
string json = Regex.Replace(input, "\\\\/\\Date[(](-?\\d+)[)]\\\\/", me, RegexOptions.None)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接