开始部分是关于 NewtownSoft 转换器,重置是关于 .Net Core Json Serializer,因为我第一次写这个答案时没有 Microsoft 序列化器
注意:NewtownSoft 和 Microsoft 有很多重叠的名称,请确保使用正确的命名空间
Newtownsoft 序列化器:
多格式支持:
这是我用的:
public class CustomDateTimeConverter : IsoDateTimeConverter
{
public CustomDateTimeConverter()
{
base.DateTimeFormat = "dd/MM/yyyy";
}
}
然后你会这样做:
public class MyObject
{
[JsonConverter(typeof(CustomDateTimeConverter))]
public DateTime Date {get;set;}
}
然后使用您之前所做的任何正常方式反序列化...
MyObject obj = JsonConvert.DeserializeObject<MyObject>(json);
另类
其他方式与@pimbrouwers 所说的相同:
public class MyObject
{
[JsonProperty("Date")] //Naturally Case Sensetive
private string dateJson {get;set;}
// it would be good to look at @pimbrouwers answer and use nullable
[JsonIgnore]
public DateTime Date
{
get
{
return DateTime.ParseExact(dateJson,"dd/MM/yyyy",CultureInfo.InvariantCulture);
}
set
{
dateJson = value.ToString("dd/MM/yyyy");
}
}
}
自定义日期时间转换器
我也只是写这个,自定义日期时间转换器,它将匹配您的自定义超出范围格式或日历
public class CustomDateTimeConverterJalali : DateTimeConverterBase
{
//I had no use for WriteJson section, i just wrote it, so i do not guarantee it working
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
return;
}
var nullableType = Nullable.GetUnderlyingType(value.GetType());
var isNullable = nullableType != null;
DateTime date;
if (isNullable)
date = ((DateTime?) value).Value;
else
date = (DateTime) value;
PersianCalendar pc = new PersianCalendar();
writer.WriteValue(pc.GetYear(date) + "/" + pc.GetMonth(date) + "/" + pc.GetDayOfMonth(date));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
//this should likely be null, but since the provider json returned empty string, it was unavoidable... (i'm not sure what we will read using reader, if data is actually null on the json side, feel free to experiment
if (string.IsNullOrWhiteSpace((string) reader.Value))
{
return null;
}
var strDate = reader.Value.ToString();
PersianCalendar pc = new PersianCalendar();
var dateParts = strDate.Split('/');
DateTime date = pc.ToDateTime(int.Parse(dateParts[0]), int.Parse(dateParts[1]), int.Parse(dateParts[2]),
0, 0, 0, 0);
return date;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);//DateTime=>true | DateTime?=>true
}
}
注意:
您提供的其他方式是一次性配置的,并且可能更简单,并且在大多数情况下都可以使用,...但是在这里,提供者为我提供了一项服务,该服务以两种格式提供日期对象,其中一个对象在不同的日历中提供两个日期......所以很高兴知道我在这里提供的这两种方式
微软序列化器:
[ASP.NET CORE MVC] 自定义 DateTimeConverter(通过默认 JSON 序列化程序):
注意,JSON 转换器的 Microsoft 实现与 NewtownSoft 实现不同。我希望 NewtownSoft 的旗帜不会很快倒下,因为他们把所有的生命都放在了上面,但是人们倾向于使用那些当权者的图书馆,所以就在这里。
注意另外,微软的实现要求您分别实现包括 Nullable 和 non-Nullable 的每种类型的数据。
我是这样做的,我创建了一个包含所有共享内容的基类,然后为每个版本创建一个简单的派生类。
基地:
using System;
using System.Buffers;
using System.Buffers.Text;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Charter724.Helper.JsonConverter.Microsoft
{
/// <summary>
/// Base Custom Format DateTime Handler <br/>
/// using System.Text.Json.Serialization;
/// </summary>
[SuppressMessage("ReSharper", "RedundantBaseQualifier")]
public class MsBaseDateTimeConverter<T> : JsonConverter<T>
{
private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
private readonly string _format;
private readonly CultureInfo _culture;
private readonly DateTimeStyles _dateTimeStyles;
public MsBaseDateTimeConverter(string format, CultureInfo culture = null, DateTimeStyles dateTimeStyles= DateTimeStyles.RoundtripKind)
{
_format = format;
if (culture == null)
{
_culture = CultureInfo.CurrentCulture;
}
_dateTimeStyles = dateTimeStyles;
}
public override bool CanConvert(Type typeToConvert)
{
if (typeToConvert == typeof(DateTime) || typeToConvert == typeof(DateTime?))
{
return true;
}
return false;
}
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
bool nullable = ReflectionUtils.IsNullableType(typeToConvert);
if (reader.TokenType == JsonTokenType.Null)
{
if (!nullable)
{
throw new JsonException();
}
return default;
}
if (_format != null)
{
if (DateTime.TryParseExact(reader.GetString(), _format, _culture, _dateTimeStyles,
out var dtValue))
{
return (T) (object) dtValue;
}
throw new JsonException();
}
else
{
// try to parse number directly from bytes
ReadOnlySpan<byte> span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan;
if (Utf8Parser.TryParse(span, out DateTime dtValue, out int bytesConsumed) &&
span.Length == bytesConsumed)
return (T) (object) dtValue;
// try to parse from a string if the above failed, this covers cases with other escaped/UTF characters
if (DateTime.TryParse(reader.GetString(), out dtValue))
return (T) (object) dtValue;
return (T) (object) reader.GetDateTime();
}
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
if (value != null)
{
if (value is DateTime dateTime)
{
if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
|| (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
{
dateTime = dateTime.ToUniversalTime();
}
var text = dateTime.ToString(_format ?? DefaultDateTimeFormat, _culture);
writer.WriteStringValue(text);
}
else
{
throw new JsonException();
}
return;
}
writer.WriteNullValue();
}
}
}
不可为空的派生的:
using System;
using System.Diagnostics.CodeAnalysis;
namespace Charter724.Helper.JsonConverter.Microsoft
{
/// <summary>
/// Format: yyyy-MM-dd - NOT NULL <br/>
/// Microsoft <br/>
/// using System.Text.Json.Serialization;
/// </summary>
[SuppressMessage("ReSharper", "RedundantBaseQualifier")]
public class MsCustomDateTimeConverter : MsBaseDateTimeConverter<DateTime>
{
public MsCustomDateTimeConverter():base("yyyy-MM-dd")
{
//base.DateTimeFormat = "yyyy-MM-dd";
}
}
}
可空的派生的:
using System;
using System.Diagnostics.CodeAnalysis;
namespace Charter724.Helper.JsonConverter.Microsoft
{
/// <summary>
/// Format: yyyy-MM-dd - NULLABLE <br/>
/// Microsoft <br/>
/// using System.Text.Json.Serialization;
/// </summary>
[SuppressMessage("ReSharper", "RedundantBaseQualifier")]
public class MsCustomDateTimeConverterNullable : MsBaseDateTimeConverter<DateTime?>
{
public MsCustomDateTimeConverterNullable():base("yyyy-MM-dd")
{
//base.DateTimeFormat = "yyyy-MM-dd";
}
}
}
使用详情:
public class MyObject
{
[System.Text.Json.Serialization.JsonConverter(typeof(MsCustomDateTimeConverter))]
public DateTime Date { set; get; }
}
替代方案:
我没有测试 microsoft 版本是否也支持带有 JsonProperty 的私有成员,但是由于 EF Core 在这件事上失败了,我只是想指出这件事,以防它不起作用。 em>
public class MyObject
{
[JsonProperty("Date")] //Naturally Case Sensetive
private string dateJson {get;set;}
// it would be good to look at @pimbrouwers answer and use nullable
[JsonIgnore]
public DateTime Date
{
get
{
return DateTime.ParseExact(dateJson,"dd/MM/yyyy",CultureInfo.InvariantCulture);
}
set
{
dateJson = value.ToString("dd/MM/yyyy");
}
}
}
两种序列化方法的并行使用:
两种环境中的转换器(MVC 核心默认序列化器和 NewtownSoft)
使用转换器 在使用相同模型的两个环境中,您所要做的就是应用 NewtownSoft 和 Default 序列化器的两个属性,这两个不会干扰并且可以正常工作。只要确保你的接口是正确的。
public class MyObject
{
[System.Text.Json.Serialization.JsonConverter(typeof(MsCustomDateTimeConverter))]
[Newtonsoft.Json.JsonConverter(typeof(NsCustomDateTimeConverter))]
public DateTime Date { set; get; }
}