c# - 在 C# 中使用 Newtonsoft.Json.Linq 查询 JSON 操作日期字符串

标签 c# string linq datetime json.net

我注意到在使用 Newtonsoft.Json.Linq 解析 JSON 时命名空间,选择日期值会返回格式与原始 JSON 不同的字符串。这是什么原因造成的?

例如:

JSON

[
  {
    ...
    "commit": {
      ...
      "committer": {
        "name": "GitHub",
        "email": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="d3bdbca1b6a3bfaa93b4baa7bba6b1fdb0bcbe" rel="noreferrer noopener nofollow">[email protected]</a>",
        "date": "2016-12-19T11:53:13Z"
      },
      ...
    }
    ...
  }
  ...
]

C#

...
List<Commit> commits = new List<Commit>();
JArray commitsArray = JArray.Parse(rawCommits);
...
foreach (var entry in commitsArray)
{
    DateTime date;
    CultureInfo provider = CultureInfo.InvariantCulture;
    string format = "MM/dd/yyyy HH:mm:ss";

    try
    {
        date = DateTime.ParseExact((string)entry["commit"]["committer"]["date"], format, provider);
    }
    catch (FormatException ex)
    {
        date = new DateTime(0);
    }
    ...
}
...

rawCommits是使用 Microsoft.AspNetCore.WebUtilities.HttpRequestStreamReader() 获得的原始 JSON 的字符串表示形式.

我希望(string)entry["commit"]["committer"]["date"]返回与 JSON 中相同的字符串,在本例中格式为 "yyyy-MM-ddTHH:mm:ssz"但如上面的代码片段所示,它的格式为 "MM/dd/yyyy HH:mm:ss" 。为什么格式发生了变化?时间和时区标识符发生了什么变化?

我唯一能想到的是调用JArray.Parse(string)识别和操作日期。是这样吗?如果是这样,这肯定是不良行为吗?如果不是,那是怎么回事?

编辑 这可以通过 .Net Core 控制台应用程序中的以下示例来生成,添加 "Microsoft.AspNetCore.Mvc": "1.1.0"project.json文件:

using Newtonsoft.Json.Linq;
using System;

namespace JsonExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string json = "{\"date\": \"2016-12-19T11:53:13Z\"}";
            JToken jToken = JToken.Parse(json);

            Console.WriteLine(jToken["date"]);
            Console.ReadLine();
        }
    }
}

输出为19/12/2016 11:53:13 ,这很有趣,因为它是另一种格式( dd/MM/yyyy HH:mm:ss )。这可能与本地化设置有关吗?如果是这样,为什么?这也很令人困惑,因为 IIS Express 与我执行上述代码的机器运行在同一台机器上,但我认为它进行了主机本地化。这也意味着,如果我部署到与我的开发机器具有不同本地化的服务器,原始帖子中的格式说明符将因为异常而最终得到等于 new DateTime(0) 的值。 。我不明白什么?

最佳答案

您是对的,对 JArray.Parse 的调用会自动为您解析日期 ( by design )。

我认为要获取原始字符串,您需要直接使用阅读器:

var s = @"[{
            ""commit"": {
                ""committer"": {
                    ""name"": ""GitHub"",
                    ""email"": ""<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0c62637e697c60754c6b657864796e226f6361" rel="noreferrer noopener nofollow">[email protected]</a>"",
                    ""date"": ""2016-12-19T11:53:13Z""
                }
            }
        }
    ]";

    using (var sr = new StringReader(s))
    using (var jr = new JsonTextReader(sr) { DateParseHandling = DateParseHandling.None })
    {
        var arr = JArray.ReadFrom(jr);

        foreach (var entry in arr)
        {
            Console.WriteLine(entry["commit"]["committer"]["date"].ToString()); // 2016-12-19T11:53:13Z
        }
    }

关于c# - 在 C# 中使用 Newtonsoft.Json.Linq 查询 JSON 操作日期字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41268734/

相关文章:

java - 将字符串文本提取到另一个字符串中

java - 正则表达式用于查找字符串中以特定字符开头、包含 2-5 个字符且不仅仅由数字组成的单词

c# - List<T> 实现 IQueryable<T>

c# - 带有子选择的 EF Core 5.0 联合 Linq 查询不起作用

c# - 如何调试 XML 反序列化?

C# 模拟重载赋值运算符 (=)

c# - 取消订阅事件

c# - 找出一个对象是否有一个特定的类作为祖先

c# - 检查字符串是否仅包含 C# 中的数字的最快方法

c# - 分组而不复制供应商行