我想将 Nullable DateTime序列化和反序列化为JSON,但我不想用JsonConverterAttribute对其进行注释。但是,我希望将其保留在JsonSerializerSettings而不是膨胀的DTO中,并保持DTO像往常一样干净。
这是DTO:
public class Post
{
public DateTime? Created { get; set; }
}
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; }
}
答案 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