TimeSpanConverter
using System.Buffers.Text;
using System.Text.Json.Schema;
namespace System.Text.Json.Serialization.Converters
{
internal sealed class TimeSpanConverter : JsonPrimitiveConverter<TimeSpan>
{
private const int MinimumTimeSpanFormatLength = 1;
private const int MaximumTimeSpanFormatLength = 26;
private const int MaximumEscapedTimeSpanFormatLength = 156;
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.String)
ThrowHelper.ThrowInvalidOperationException_ExpectedString(reader.TokenType);
return ReadCore(ref reader);
}
internal override TimeSpan ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return ReadCore(ref reader);
}
private unsafe static TimeSpan ReadCore(ref Utf8JsonReader reader)
{
if (!JsonHelpers.IsInRangeInclusive(reader.ValueLength, 1, 156))
ThrowHelper.ThrowFormatException(DataType.TimeSpan);
ReadOnlySpan<byte> source;
if (!reader.HasValueSequence && !reader.ValueIsEscaped)
source = reader.ValueSpan;
else {
Span<byte> utf8Destination = new Span<byte>(stackalloc byte[156], 156);
int length = reader.CopyString(utf8Destination);
source = utf8Destination.Slice(0, length);
}
byte b = source[0];
if (!JsonHelpers.IsDigit(b) && b != 45)
ThrowHelper.ThrowFormatException(DataType.TimeSpan);
if (!Utf8Parser.TryParse(source, out TimeSpan value, out int bytesConsumed, 'c') || source.Length != bytesConsumed)
ThrowHelper.ThrowFormatException(DataType.TimeSpan);
return value;
}
public unsafe override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
Span<byte> destination = new Span<byte>(stackalloc byte[26], 26);
Utf8Formatter.TryFormat(value, destination, out int bytesWritten, 'c');
writer.WriteStringValue(destination.Slice(0, bytesWritten));
}
internal unsafe override void WriteAsPropertyNameCore(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options, bool isWritingExtensionDataProperty)
{
Span<byte> destination = new Span<byte>(stackalloc byte[26], 26);
Utf8Formatter.TryFormat(value, destination, out int bytesWritten, 'c');
writer.WritePropertyName(destination.Slice(0, bytesWritten));
}
internal override JsonSchema GetSchema(JsonNumberHandling _)
{
return new JsonSchema {
Type = JsonSchemaType.String,
Comment = "Represents a System.TimeSpan value.",
Pattern = "^-?(\\d+\\.)?\\d{2}:\\d{2}:\\d{2}(\\.\\d{1,7})?$"
};
}
}
}