Ben*_*enj 6 c# datetime json system.text.json
我正在尝试反序列化以下 JSON
{"serverTime":1613967667240}
Run Code Online (Sandbox Code Playgroud)
进入以下类的对象
public class ApiServerTime
{
[JsonPropertyName("serverTime")]
public DateTime ServerTime
{
get;
private set;
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下命令:
JsonSerializer.Deserialize<ApiServerTime>(jsonString);
Run Code Online (Sandbox Code Playgroud)
但生成的对象包含ServerTime == DateTime.MinValue. 我究竟做错了什么?
您还可以为 System.Text.Json 注册自定义日期格式化程序。 https://learn.microsoft.com/en-us/dotnet/standard/datetime/system-text-json-support
public class DateTimeConverterForCustomStandardFormatR : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.UnixEpoch.AddMilliseconds(reader.GetInt64());
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
// The "R" standard format will always be 29 bytes.
Span<byte> utf8Date = new byte[29];
bool result = Utf8Formatter.TryFormat(value, utf8Date, out _, new StandardFormat('R'));
Debug.Assert(result);
writer.WriteStringValue(utf8Date);
}
}
string js = "{\"ServerTime\":1613967667240}";
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new DateTimeConverterForCustomStandardFormatR());
var value = JsonSerializer.Deserialize<ApiServerTime>(js, options);
Run Code Online (Sandbox Code Playgroud)
本着构建更好的捕鼠器的精神,这里有一个支持的实现。
public class UnixToNullableDateTimeConverter : JsonConverter<DateTime?>
{
public bool? IsFormatInSeconds { get; init; }
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
try
{
if (reader.TryGetInt64(out var time))
{
// if 'IsFormatInSeconds' is unspecified, then deduce the correct type based on whether it can be represented as seconds within the .net DateTime min/max range (1/1/0001 to 31/12/9999)
// - because we're dealing with a 64bit value, the unix time in seconds can exceed the traditional 32bit min/max restrictions (1/1/1970 to 19/1/2038)
if (IsFormatInSeconds == true || IsFormatInSeconds == null && time > _unixMinSeconds && time < _unixMaxSeconds)
return DateTimeOffset.FromUnixTimeSeconds(time).LocalDateTime;
return DateTimeOffset.FromUnixTimeMilliseconds(time).LocalDateTime;
}
}
catch
{
// despite the method prefix 'Try', TryGetInt64 will throw an exception if the token isn't a number.. hence we swallow it and return null
}
return null;
}
// write is out of scope, but this could be implemented via writer.ToUnixTimeMilliseconds/WriteNullValue
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) => throw new NotSupportedException();
private static readonly long _unixMinSeconds = DateTimeOffset.MinValue.ToUnixTimeSeconds(); // -62_135_596_800
private static readonly long _unixMaxSeconds = DateTimeOffset.MaxValue.ToUnixTimeSeconds(); // 253_402_300_799
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5514 次 |
| 最近记录: |