【问题标题】:Json.NET: Converting objects to DateTimeOffsets?Json.NET:将对象转换为 DateTimeOffsets?
【发布时间】:2016-06-24 15:59:11
【问题描述】:

我正在向 API 服务发出请求,该服务以以下形式将日期返回为 JSON:

{
     "dateCreated": {
        "date":8,
        "day":4,
        "hours":22,
        "minutes":44,
        "month":10,
        "nanos":241000000,
        "seconds":46,
        "time":1194590686241,
        "timezoneOffset":480,
        "year":107
     }
}

这里time 是自 Unix 纪元以来的毫秒数,所以这确实是我要注意的唯一属性。

是否可以编写一个自定义的 Json.NET 转换器,将其反序列化为类似的东西

public class ApiResponse
{
    public ApiResponse(DateTimeOffset dateCreated)
    {
        DateCreated = dateCreated;
    }

    public DateTimeOffset DateCreated { get; }
}

(转换器将在对象的time 属性上调用DateTimeOffset.FromUnixTimeMilliseconds。)

这是我目前的代码:

public class ApiDateConverter : JsonConverter
{
    public override bool CanWrite => false;

    public override bool CanConvert(Type objectType)
    {
        return typeof(DateTimeOffset) == objectType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // What type is existingValue here? How do I get existingValue.time?
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException();
    }
}

【问题讨论】:

    标签: c# .net json serialization json.net


    【解决方案1】:

    选项 1:您的 ApiDateConverter 可以通过以下方式完成:

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            dynamic jObject = JObject.Load(reader);
    
            return DateTimeOffset.FromUnixTimeMilliseconds(jObject.time.Value);
        }
    

    选项 2:不使用自定义转换器:

    public class DateSerialized
    {
        public int date { get; set; }
        public int day { get; set; }
        public int hours { get; set; }
        public int minutes { get; set; }
        public int month { get; set; }
        public int nanos { get; set; }
        public int seconds { get; set; }
        public long time { get; set; }
        public int timezoneOffset { get; set; }
        public int year { get; set; }
    }
    
    public class ApiResponse
    {
        [JsonIgnore]
        public DateTimeOffset DateCreated => DateTimeOffset.FromUnixTimeMilliseconds(DateSerialized.time);
    
        [JsonProperty("dateCreated")]
        private DateSerialized DateSerialized { get; set; }
    }
    

    【讨论】:

      【解决方案2】:

      当然可能编写一个 Json.Net 转换器将 JSON 直接转换为您的域对象,但我不建议这样做。

      相反,我建议您创建一个镜像数据的 DTO(数据传输对象):

      public class DateDto
      {
          public long Time { get; set; }
      }
      

      然后让 Json.Net 反序列化到这个对象中。

      一旦你有了它,你可以创建一个纯.Net转换器,将DateDto映射到DateTime或任何你想要的结构(假设你使用的是NodaTime库而不是.Net的DateTime) .

      通过这样做,您省去了实现自定义反序列化逻辑的麻烦,并且您遵循 SOLID 中的 S:单一职责原则。您有一个仅用于表示数据的对象,以及一个将其转换为您的应用程序使用的任何内容的转换器。

      它还增加了代码的可测试性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-01
        • 2013-04-09
        • 2014-03-26
        • 2016-09-25
        相关资源
        最近更新 更多