【问题标题】:replace a JSON date in a string to a more readable date将字符串中的 JSON 日期替换为更易读的日期
【发布时间】:2012-04-18 12:58:41
【问题描述】:

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

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

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

我想要做的是在 JSON (C#) 字符串中用“正常”日期替换那些 JSON 日期,所以在后面的代码中,在我将字符串添加到 PRE 元素之前。

我正在考虑一些正则表达式,但我无法弄清楚如何......

【问题讨论】:

  • 您能否在问题的文本中包含更完整的 JSON 字符串示例,您希望它更“可读”。问题是 JSON 将主要用于将对象转换为字符串,以便能够传输到 Web 客户端并将 JSON 转换回 JavaScript 对象。 JavaScript 对象应该是不可读的。例如,如果您有一个对象数组,其属性中的日期为一个,则您无法使其对人类具有良好的可读性。因此,了解您已序列化为 JSON 字符串的哪种数据(哪个对象)非常重要。
  • 您会考虑使用 JavaScript 解决方案,还是一心想要使用 C# 进行转换?

标签: c# regex json


【解决方案1】:

我已经处理 JSON 字符串中的日期有一段时间了,there's no standard way 为此,这就是为什么有这么多不同的方法来做到这一点!如果 JSON 规范首先可以指定日期的标准格式,也许会更好!

Microsoft 以自己的方式进行操作,以 UTC 格式计算自 1970 年以来的毫秒数,类似于 "/Date(1319266795390+0800)/"

自从在ASP.Net JavaScriptSerializer 输出之上使用正则表达式以来,我们一直将上述字符串更改为ISO-8601 format。它是 W3C 标准,人类可读,也是大多数浏览器将 Date 序列化为字符串的方式,方法如下:

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");
    });
}

您可以轻松更改格式以满足您的需求,查看自定义日期和时间格式check out MSDN article here

它的使用方法如下:

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

更新:

还有一种方法可以使用 Regex 将 JavaScript 中从服务器返回的 JSON 字符串调整为更易读的形式:

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

【讨论】:

  • 不错的解决方案。我们正在使用自动将对象转换为 JSON 的 WCF 框架。在代码中,我们只返回一个带有数据成员属性注释的 POCO 对象,当调用该函数时,由于我认为项目类型的性质,输出将转换为 JSON。我想说的是(据我所知)在代码中没有任何时刻/位置可以让我使用自定义数据替换代码
  • WCF 使用DataContractJsonSerializer 来序列化 POCO/DataContract 对象,您可以调整默认的 JSON 序列化器,并将DataContractJsonSerializer 替换为自定义序列化器!这是一个向您展示如何操作的帖子:blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/… 无论如何,有一种替代方法可以使用 JavaScript 中的正则表达式调整从服务器返回的 JSON 文本,正如我将在上面的更新中展示的那样
  • 这适用于 Date(##) 但不适用于 Date(##+####) 即不包含任何时区信息。尝试在此字符串上执行此操作:"{\"EndTime\":\"\\/Date(1381479678557)\\/\",\"StartTime\":\"\\/Date(1381479678557+0200)\\ /\"}"。它只替换 EndTime 而不是 StartTime
【解决方案2】:

解决方案在问题中显示的字符串内。 JavaScript Date 对象将解析该格式并生成可读版本,因此Date(1319266795390+0800) 返回“Wed Apr 18 2012 08:13:22 GMT-0500 (Central Daylight Time)”。

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

【讨论】:

  • 啊,但我的字符串包含的不仅仅是那个日期,它还包含 50 个其他人的属性,其中有几个日期。
  • Michel - 正则表达式本质上旨在从很长的字符串中检索特定数据。 Eric 建议的应该对你有用的东西可以完全用 JavaScript 来完成。
【解决方案3】:

你可以用这个:

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")));

【讨论】:

    【解决方案4】:

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

    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()

    【讨论】:

      【解决方案5】:

      用作正则表达式,例如:

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

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

      使用您在匹配评估器委托中获得的Match 对象并提取刻度、区域符号、区域小时和区域分钟部分,将其转换为整数。

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

      【讨论】:

        【解决方案6】:

        如果您的 JSON 是 .NET 类的序列化表示,也许您可​​以使用 DataContractJsonSerializer 在服务器上对其进行反序列化,或者您可以只为您的 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;
        }
        

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

                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); }
                }
            

            因为这将返回字符串,所以它在客户端是相同的,所以也从用户那里获取字符串 dateTime 并转换它。

            【讨论】:

              【解决方案9】:
              string input = [yourjsonstring]; 
              MatchEvaluator me = new MatchEvaluator(MTListServicePage.MatchDate);
              string json = Regex.Replace(input, "\\\\/\\Date[(](-?\\d+)[)]\\\\/", me, RegexOptions.None)
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-03-07
                • 2012-06-04
                • 1970-01-01
                • 2011-11-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多