日期不能序列化或反序列化

本文关键字:反序列化 序列化 不能 日期 | 更新日期: 2023-09-27 18:13:15

我想序列化和反序列化Nullable DateTime到/从JSON,但我不想用JsonConverterAttribute注释它。然而,我想把它放在JsonSerializerSettings中的一个地方,而不是用这些属性使dto像往常一样干净。

这里是DTO:

public class Post
{
    public DateTime? Created { get; set; }
}

这里是自定义JsonConverter:

internal class EpochDateTimeConverter : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(DateTime).IsAssignableFrom(objectType);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var t = (long)Convert.ToDouble(reader.Value.ToString());
        return t.FromUnixTime();
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        long ticks;
        DateTime valueAsDate = (DateTime)value;
        if (valueAsDate != DateTime.MinValue)
        {
            if (value is DateTime)
            {
                var epoc = new DateTime(1970, 1, 1);
                var delta = (valueAsDate) - epoc;
                if (delta.TotalSeconds < 0)
                {
                    throw new ArgumentOutOfRangeException("Unix epoc starts January 1st, 1970");
                }
                ticks = (long)delta.TotalSeconds;
            }
            else
            {
                throw new Exception("Expected date object value.");
            }
            writer.WriteValue(ticks);
        }
    }
}

这是最小的复制:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace NameSpaceSample
{
  public class Post
  {
    public DateTime? Created { get; set; }
  }
  public class Program
  {
      public static void Main(string[] args)
      {
         var settings = new JsonSerializerSettings()
         {
            NullValueHandling = NullValueHandling.Ignore,
            Converters = new List<JsonConverter>
            {
               new EpochDateTimeConverter()
            }
         };
         string postAsJson = JsonConvert.SerializeObject(new Post { Created = DateTime.UtcNow }, settings);
         Console.WriteLine(postAsJson);// {"Created":"2015-09-17T17:15:06.6160689Z"}
         var json = "{'"Created'":1442510191}";
         Post post = JsonConvert.DeserializeObject<Post>(json, settings);//Exception here
         Console.ReadKey();
       }
    }
}

该行抛出的异常是:

JsonReaderException: 
Error reading date. Unexpected token: Integer. Path 'Created', line 1, position 21.

注意:

我知道这可以通过用JsonConverterAttribute注释它来解决,但我不想这样做,因为前面提到的原因。

public class Post
{
  [JsonConverter(typeof(EpochDateTimeConverter))]
  public DateTime? Created { get; set; }
}

日期不能序列化或反序列化

我自己想出来的。我只需要改变CanConvert函数如下:

public override bool CanConvert(Type objectType)
{
   return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
}

这不是很容易找到。把我的答案放在这里,以帮助其他人,如果他们遇到这样的问题。

我给你从一个对象到另一个对象的方式,这样你就不用担心转移任何东西,谢谢

  public static T ConvertTo<T>(this object value)
        {
            T returnValue = default(T);
            if (value is T)
            {
                returnValue = (T)value;
            }
            else
            {
                try
                {
                    returnValue = (T)Convert.ChangeType(value, typeof(T));
                }
                catch (InvalidCastException)
                {
                    returnValue = default(T);
                }
            }
            return returnValue;
        }

JsonConverterCanConvert(Type objectType)方法决定该转换器是否将用于正在序列化/反序列化的当前属性。

由于您的属性类型是DateTime?,并且不能从DateTime分配,它返回false,然后不使用转换器。

你只需要改变方法如下:

public override bool CanConvert(Type objectType)
{
    return typeof(DateTime?).IsAssignableFrom(objectType);
}