c# - 如何使用 JSON.Net 转换新的日期(年、月、日)重载

标签 c# datetime json.net

我正在尝试解析日期定义为 JavaScript objects 的 JSON 文件:

new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);

所以我确实尝试用 JavaScriptDateTimeConverter 解析它

测试.json:

{"data" : [{"Date" : new Date(2015, 06, 01, 00, 00, 00)}]}

c#:

using (StreamReader file = File.OpenText(@"c:\test.json"))
{
  JsonSerializer serializer = new JsonSerializer();
  serializer.Converters.Add(new JavaScriptDateTimeConverter());
  Rootobject deserializedRoot = (Rootobject)serializer.Deserialize(file, typeof(Rootobject));
}

不幸的是我收到了这个错误:

Unexpected token parsing date. Expected EndConstructor, got Integer. Path 'data[0].Date1', line 13, position 30.

根据我的理解,JSON.Net 最多期望一个 new Date(52231943) 但不处理 Javascript Date() 对象的构造函数重载。

是否有任何已知的方法来转换新日期(年、月、日)

最佳答案

您可以创建自己的 JavaScriptDateTimeConverter.cs 的子类像这样:

public class JavaScriptYMDDateTimeConverter : JavaScriptDateTimeConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Type type = (Nullable.GetUnderlyingType(objectType) ?? objectType);
        bool isNullable = (Nullable.GetUnderlyingType(objectType) != null);

        var token = JToken.Load(reader);
        if (token == null || token.Type == JTokenType.Null)
        {
            if (!isNullable)
                throw new JsonSerializationException(string.Format("Null value for type {0} at path {1}", objectType.Name, reader.Path));
            return null;
        }
        if (token.Type != JTokenType.Constructor)
        {
            throw new JsonSerializationException(string.Format("Invalid Date constructor \"{0}\" at path {1}", token.ToString(), reader.Path));
        }
        var constructor = (JConstructor)token;
        if (!string.Equals(constructor.Name, "Date", StringComparison.Ordinal))
        {
            throw new JsonSerializationException(string.Format("Invalid Date constructor \"{0}\" at path {1}", token.ToString(), reader.Path));
        }

        var values = constructor.Values().ToArray();

        if (values.Length == 0)
        {
            throw new JsonSerializationException(string.Format("Invalid Date constructor \"{0}\" at path {1}", token.ToString(), reader.Path));
        }
        else if (values.Length == 1)
        {
            // Assume ticks
            using (var subReader = constructor.CreateReader())
            {
                while (subReader.TokenType != JsonToken.StartConstructor)
                    subReader.Read();
                return base.ReadJson(subReader, objectType, existingValue, serializer); // Use base class to convert
            }
        }
        else
        {
            var year = (values.Length > 0 ? (int)values[0] : 0);
            var month = (values.Length > 1 ? (int)values[1] : 0) + 1; // c# months go from 1 to 12, JavaScript from 0 to 11
            var day = (values.Length > 2 ? (int)values[2] : 0);
            var hour = (values.Length > 3 ? (int)values[3] : 0);
            var min = (values.Length > 4 ? (int)values[4] : 0);
            var sec = (values.Length > 5 ? (int)values[5] : 0);
            var ms = (values.Length > 6 ? (int)values[6] : 0);

            // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
            // Note: Where Date is called as a constructor with more than one argument, the specifed arguments represent local time.
            var dt = new DateTime(year, month, day, hour, min, sec, ms, DateTimeKind.Local);
            if (type == typeof(DateTimeOffset))
                return new DateTimeOffset(dt);
            return dt;
        }
    }
}

此处 ReadJson() 将 token 加载到 JConstructor 中, 检查 constructor nameDate,然后解析子项。

请注意,我没有重写 WriteJson,因此此转换器将以与 JavaScriptDateTimeConverter 相同的样式编写,其中刻度显示为构造函数的单个参数。

用它代替 JavaScriptDateTimeConverter()

关于c# - 如何使用 JSON.Net 转换新的日期(年、月、日)重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31577833/

相关文章:

c# - Newtonsoft.Json DLL 版本与 signalR + WEBAPI 冲突

c# - 如何使用 json.net 反序列化派生类

c# - JsonReaderException - 解析值时遇到意外字符

c# - C#中的继承概念

c# - 在 C# 中,是否可以将 List<Child> 转换为 List<Parent>?

datetime - 如何使用 XSLT 将刻度转换为可读的日期时间?

javascript - 如何在 JavaScript 中获取特定的日期时间格式

python - PySpark:在日期为字符串的范围内按日期字段过滤 DataFrame

c# - 参数为 sbyte 类型的 GetBytes

c# - 如何在 Xamarin Forms 中将行为转换为泛型类型?