关于c#:将字符串中的JSON日期替换为更易读的日期

replace a JSON date in a string to a more readable date

我们想向正在测试我们的应用程序的用户展示一些JSON。因此,我们在ASP.NET代码隐藏文件中调用REST服务,并返回一个字符串,该字符串包含大量JSON。

然后我们把它放在页面的一个pre元素中,调用beautify来创建可读性很好的JSON,一切都很好:显示了人类可读的内容。

很好,但有一件事:所有日期都以普通JSON格式显示,如"日期(1319266795390+0800)"/"

我要做的是用json(c)字符串中的"正常"日期替换这些json日期,因此在将字符串添加到pre元素之前,在后面的代码中也就是说。

我在想一些雷吉,但我不知道怎么…


我用JSON字符串处理日期已经有一段时间了,没有标准的方法,这就是为什么有这么多不同的方法可以做到的原因!如果JSON规范可以首先为日期指定一种标准格式,也许会更好!

微软正以自己的方式进行这项工作,以UTC格式计算1970年以来的毫秒数,这类似于"/Date(1319266795390+0800)/"

自从在ASP.Net JavaScriptSerializer输出上使用正则表达式以来,我们一直将上述字符串改为iso-8601格式。这是一个W3C标准,人类可读,大多数浏览器将日期序列化为字符串的方式,如下所示:

1
2
3
4
5
6
7
8
9
10
11
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文章

使用方法如下:

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

更新:

还有一种方法可以使用regex将服务器以javascript形式返回的json字符串调整为更可读的形式:

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


解决方案在问题中显示的字符串内。javascript日期对象将解析该格式并生成可读版本,因此Date(1319266795390+0800)返回"Wed Apr 18 2012 08:13:22 GMT-0500(中央夏令时)"。

要从字符串中删除正斜杠,可以使用带有正则表达式的replace函数:"/Date(1319266795390+0800)/".replace(/\//g, '')


您可以使用:

1
2
3
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")));


假设要序列化的类如下所示:

1
2
3
4
5
6
public class Something
{
    public int ID;
    public string Name;
    public DateTime Date;
}

更改为:

1
2
3
4
5
6
7
public class Something
    {
        public int ID;
        public string Name;
        public DateTime Date;
        public string HumanReadableDate { get { return Date.ToLongDateString(); } }
    }

或者,如果希望该额外属性仅在测试环境中显示:

1
2
3
4
5
6
7
8
9
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()


创建一个字符串属性,例如我在这里定义的出生日期,并将datetime变量返回为:

1
2
3
4
5
    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); }
    }

因为这将返回字符串,所以在客户端so和aslo将从用户那里获取字符串datetime并转换它。


使用newtonsoft.json。您可以为每种类型提供自己的序列化程序,并根据需要序列化日期。

http://james.newtonking.com/projects/json-net.aspx


如果您的JSON是.NET类的串行表示,那么您可以使用DataContractJsonSerializer在服务器上对其进行反序列化,或者,如果您不需要处理多个数据集的通用解决方案,您可以为JSON对象定义一个存根类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
}


用作regex,例如:

1
2
3
4
5
6
7
(?<= /Date\( )
  (?<ticks>[0-9]+)
  ((?<zonesign>[+-])
   (?<zonehour>[0-9]{2})
   (?<zoneminutes>[0-9]{2})
  )?
(?= \)/ )

这将与/Date(1319266795390+0800)/括号内的部分匹配。然后,您可以对整个JSON字符串调用Regex.Replace,用格式良好的DateTime替换数字:

使用Match Evaluator委托中获得的Match对象,提取ticks、zonesign、zonehour和zoneeminutes部分,将其转换为整数。

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


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