【问题标题】:Newtonsoft deserialize doesn't convert string to DateTimeNewtonsoft 反序列化不会将字符串转换为 DateTime
【发布时间】:2019-11-26 18:59:56
【问题描述】:

我正在使用 Facebook Graph API,它返回一个 json 对象,该对象包含以下格式的字符串中的日期时间:“created_time”:“2013-01-25T00:11:02+0000”

反序列化的对象包含这个日期时间:“0001-01-01 00:00:00”,我想它相当于 null。如何正确反序列化日期时间字符串?

这是我的 DTO 课程:

using System;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using Newtonsoft.Json.Converters;
using project.DTOs;

namespace project.DTOs.Facebook
{
    public class FacebookCommentResponseDto
    {
        [JsonPropertyName("id")]
        public string Id { get; set; }
        [JsonPropertyName("from")]
        public FacebookUserDto From { get; set; }
        [JsonPropertyName("message")]
        public string Message { get; set; }
        [JsonPropertyName("created_time")]
        [JsonConverter(typeof(CustomDateTimeConverter))]
        public DateTime CreatedTime { get; set;}
    }
    internal class CustomDateTimeConverter : IsoDateTimeConverter
    {
        public CustomDateTimeConverter()
        {
            base.DateTimeFormat = "yyyy-MM-ddTH:mm:ss.fffK";
        }
    }
}

这是我反序列化对象的代码:

var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(result);

【问题讨论】:

  • ISO 8601格式。如果您想要 unix 时间戳(进行转换),您可以在通话中添加 date_format=USee 那里有更多关于转换 ISO 8601 格式的信息。
  • 可能你的格式有点不对劲? yyyy-MM-ddTH:mm:ss.fffK --> yyyy-MM-ddTHH:mm:ss.ffK(添加了一个 H 并删除了一个 f 因为您期望的格式似乎有两位数的小时和两位数的毫秒以及)
  • 通过添加 H 并删除 f 来更改格式不起作用。我究竟如何添加date_format=U
  • @Mattieeec3 可能没有帮助,但重新阅读,它应该是 yyyy-MM-ddTHH:mm:ssK 因为没有提供毫秒。
  • 我现在也试过了,可惜没用。

标签: c# asp.net .net asp.net-mvc asp.net-core


【解决方案1】:

在您的代码中,您有 using Newtonsoft.Json.Converters;using System.Text.Json.Serialization;。在FacebookCommentResponseDto 上,您使用属于System.TextJsonPropertyName,但转换器类CustomDateTimeConverter 旨在与Newtonsoft.Json 属性JsonProperty 一起使用,而不是与System.Text 属性JsonPropertyName 一起使用。因此,在您的代码中,转换器永远不会被调用。

一种解决方案是删除using System.Text.Json.Serialization; 并将FacebookCommentResponseDto 中的JsonPropertyName 替换为JsonProperty。这意味着您只使用Newtonsoft.Json,然后日期转换甚至可以在没有转换器的情况下开箱即用。以下测试为绿色:

using Newtonsoft.Json;
using System;
using Xunit;

namespace XUnitTestProject1
{
    public class TimeFormatUnitTest
    {
        [Fact]
        public void ParseCreatedTime()
        {
            var timeString = "2013-01-25T00:11:02+0000";
            var json = "{ \"created_time\": \"" + timeString + "\" }";

            var data = JsonConvert.DeserializeObject<FacebookCommentResponseDto>(json);

            Assert.Equal(DateTime.Parse(timeString), data.CreatedTime);
        }
    }

    public class FacebookCommentResponseDto
    {
        [JsonProperty("created_time")]
        public DateTime CreatedTime { get; set; }
    }
}

【讨论】:

  • 解释为什么需要这样做(事实上他的转换器适用于 Newtonsoft 而属性适用于System.Text.Json)并且您已经回答了
  • @ColinM 谢谢你的建议。我编辑了我的帖子并尽力解释它。如果您认为有必要,请随时对其进行编辑。
【解决方案2】:

正如 Marius 所说,您的转换器适用于 Newtonsoft,而属性适用于 System.Text.Json。您可以将 [JsonPropertyName] 更改为 [JsonProperty]

另一种解决方案是在System.Text.Json 中实现JsonConverter&lt;DateTime&gt; 的自定义转换器:

1.转换器:

public class FacebookCommentResponseDto
{
    [JsonPropertyName("id")]
    public string Id { get; set; }

    [JsonPropertyName("message")]
    public string Message { get; set; }
    [JsonPropertyName("created_time")]
    [JsonConverter(typeof(CustomDateTimeConverter))]
    public DateTime CreatedTime { get; set; }
}
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        Debug.Assert(typeToConvert == typeof(DateTime));
        return DateTime.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

2.反序列化:

var time = "2013-01-25T00:11:02+0000";
var ID = "1001";                    
var result = "{ \"created_time\": \"" + time + "\", \"id\": \"" + ID + "\" }";
var data = System.Text.Json.JsonSerializer.Deserialize<FacebookCommentResponseDto>(result);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2016-08-07
    相关资源
    最近更新 更多