您的DateTimeOffset
值嵌入在一个对象中,如下所示:
{"_date":"2021-04-07T18:18:00.000Z"}
并且您想提取_date
要返回的内部属性的值。您可以使用以下JsonConverter<DateTime>.Read()
方法执行此操作:
public class DateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
const string TZDateFormat = "O"; // Your custom format (not shown in your question).
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) =>
// Write as a simple string.
writer.WriteStringValue(value.ToString(TZDateFormat, CultureInfo.InvariantCulture));
const string _date = "_date";
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.String:
// A simple DateTimeOffset string "value"
return DateTimeOffset.ParseExact(reader.GetString(), TZDateFormat, CultureInfo.InvariantCulture);
case JsonTokenType.StartObject:
{
// A DateTimeOffset string embedded in an object { "_date" : "value" }
using var doc = JsonDocument.ParseValue(ref reader);
if (doc.RootElement.TryGetProperty(_date, out var value))
return DateTimeOffset.ParseExact(value.GetString(), TZDateFormat, CultureInfo.InvariantCulture);
return default(DateTimeOffset); // Or throw an exception?
}
default:
throw new JsonException(); // Unknown token type
}
}
}
在您的Read()
方法中,您尝试将返回的值加载reader.GetString()
到 aJsonDocument
中,但在方法的开头,阅读器位于StartObject
令牌而不是值字符串上,并且reader.GetString()
只返回当前令牌的字符串值,而不是当前令牌及其你似乎想要的孩子。要将当前令牌及其子代加载到 aJsonDocument
中,请使用JsonDocument.ParseValue(Utf8JsonReader)
.
(顺便说一句,JsonDocument
是一次性的,实际上必须将池化的内存返回到内存池。)
如果您想避免构建 a JsonDocument
,您可以直接使用Utf8JsonReader
以下方式通过 JSON 流式传输:
static byte [] _date = Encoding.UTF8.GetBytes("_date");
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
case JsonTokenType.String:
// A simple DateTimeOffset string "value"
return DateTimeOffset.ParseExact(reader.GetString(), TZDateFormat, CultureInfo.InvariantCulture);
case JsonTokenType.StartObject:
{
// A DateTimeOffset string embedded in an object { "_date" : "value" }
DateTimeOffset? value = null;
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.EndObject:
return value.GetValueOrDefault();
case JsonTokenType.PropertyName:
var match = reader.ValueTextEquals(_date);
reader.Read();
if (match)
value = DateTimeOffset.ParseExact(reader.GetString(), TZDateFormat, CultureInfo.InvariantCulture);
else
reader.Skip();
break;
default:
throw new JsonException();
}
}
}
break;
}
throw new JsonException();
}
这有点复杂,但也应该更高效。
在这两种情况下,我都会检查传入的值是对象还是简单的字符串。如果是一个简单的字符串,我会继续将其解析为DateTimeOffset
.
演示小提琴在这里。