日期无法序列化或反序列化

时间:2015-09-17 17:41:36

标签: c# json.net

我想将 Nullable DateTime序列化和反序列化为JSON,但我不想用JsonConverterAttribute对其进行注释。但是,我希望将其保留在JsonSerializerSettings而不是膨胀的DTO中,并保持DTO像往常一样干净。

这是DTO:

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

以下是Custom 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; }
}

3 个答案:

答案 0 :(得分:0)

自己想出来。我只需将CanConvert函数更改为以下内容:

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

找出来并不容易。如果他们遇到这个问题,请将我的答案放在这里以帮助他人。

答案 1 :(得分:0)

我告诉你从任何物体到另一个物体的方式,这样你就不用担心转移任何东西了,谢谢

  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;
        }

答案 2 :(得分:0)

CanConvert(Type objectType)的{​​{1}}方法确定该转换器是否将用于正在序列化/反序列化的当前属性。

由于您的媒体资源类型为JsonConverter且无法从DateTime?转让,因此会返回false,然后转换器才会被使用。

您只需将方法更改为以下内容:

DateTime