首页 > 解决方案 > 将日期 json 解析为 DateTime

问题描述

JSON是:

{"date":13,"day":5,"hours":19,"minutes":6,"month":10,"nanos":0,"seconds":41,"time":1605265601000,"timezoneOffset":-480,"year":120}

当我尝试转换为时DateTime,我遇到了以下错误:

Newtonsoft.Json.JsonReaderException HResult=0x80131500 消息=解析值时遇到意外字符:{。路径'',第 1 行,位置 1。Source=Newtonsoft.Json StackTrace:在 Newtonsoft.Json.JsonTextReader.ReadAsDateTime() 在 Newtonsoft.Json.Json.JsonTextReader.ReadStringValue(ReadType readType) 在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType( JsonReader reader, JsonContract contract, Boolean hasConverter) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert .DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value,

我的代码:

var txt = "{\"date\":13,\"day\":5,\"hours\":19,\"minutes\":6,\"month\":10,\"nanos\":0,\"seconds\":41,\"time\":1605265601000,\"timezoneOffset\":-480,\"year\":120}";
var aa = Newtonsoft.Json.JsonConvert.DeserializeObject<DateTime>(txt);
Console.ReadKey();

当我改用 Newtonsoft.Json.dll 3.5 版本时,错误消失了。当我改用 Newtonsoft.Json.dll 9.0 版本时,会出现错误。

我正在使用 VS2017 构建,我的错误在哪里?

标签: c#json

解决方案


我怀疑 Json.NET 现在希望DateTime将值表示为字符串,而不是 JSON 对象。当然,你得到的代表是一个不寻常的代表。我建议您创建自己的遵循 JSON 的类,并编写一个ToDateTime(或更好的ToDateTimeOffset)来转换它。

(我真的很惊讶 Json.NET 的早期版本完全可以处理这个问题。)

更好的是,如果您可以控制创建此 JSON 的代码,最好将其更改为更合理的格式,例如 ISO-8601 字符串。

这是执行转换的代码示例。DateTimeOffset由于工作方式和偏移的表达方式混合在一起,偏移处理有点奇怪:(

using System;
using Newtonsoft.Json;

class Test
{
    static void Main()
    {
        var txt = "{\"date\":13,\"day\":5,\"hours\":19,\"minutes\":6,\"month\":10,\"nanos\":0,\"seconds\":41,\"time\":1605265601000,\"timezoneOffset\":-480,\"year\":120}";
        var jdto = JsonConvert.DeserializeObject<JsonDateTimeOffset>(txt);
        var dto = jdto.ToDateTimeOffset();
        Console.WriteLine(dto);
        Console.WriteLine(dto.ToUniversalTime());
    }
}

public class JsonDateTimeOffset
{
    // All ignored as the Time property handles all these.
    public int Date { get; set; }
    public int Day { get; set; }
    public int Hours { get; set; }
    public int Minutes { get; set; }
    public int Seconds { get; set; }
    // Ignored, as we don't know what it means.
    public int Nanos { get; set; }
    
    // Milliseconds since the unix epoch
    public long Time { get; set; }
    
    // UTC offset in minutes, but reversed from the normal
    // view.
    [JsonProperty("timezoneOffset")]
    public int TimeZoneOffset { get; set; }
    
    public DateTimeOffset ToDateTimeOffset()
    {
        var instant = DateTimeOffset.FromUnixTimeMilliseconds(Time);
        var offset = -TimeSpan.FromMinutes(TimeZoneOffset);
        return new DateTimeOffset(instant.DateTime + offset, offset);
    }
}

推荐阅读