Skip to content

Commit cde8b30

Browse files
committed
Refactoring of System.Text.Json serializers to avoid repetition for value types
1 parent 4ee939c commit cde8b30

File tree

2 files changed

+36
-38
lines changed

2 files changed

+36
-38
lines changed

src/NodaTime.Serialization.SystemTextJson/NodaConverters.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,19 @@ public static JsonConverter<DateTimeZone> CreateDateTimeZoneConverter(IDateTimeZ
117117
/// <summary>
118118
/// Converter for durations using <see cref="DurationPattern.JsonRoundtrip"/>.
119119
/// </summary>
120-
public static JsonConverter DurationConverter { get; }
120+
public static JsonConverter DurationConverter => DurationConverterImpl;
121+
122+
// Note: this only exists because DurationConverter is non-generic.
123+
internal static JsonConverter<Duration> DurationConverterImpl { get; }
121124
= new NodaPatternConverter<Duration>(DurationPattern.JsonRoundtrip);
122125

123126
/// <summary>
124127
/// Converter for durations using <see cref="DurationPattern.Roundtrip"/>.
125128
/// </summary>
126-
public static JsonConverter RoundtripDurationConverter { get; }
129+
public static JsonConverter RoundtripDurationConverter => RoundtripDurationConverterImpl;
130+
131+
// Note: this only exists because RoundtripDurationConverter is non-generic.
132+
internal static JsonConverter<Duration> RoundtripDurationConverterImpl { get; }
127133
= new NodaPatternConverter<Duration>(DurationPattern.Roundtrip);
128134

129135
/// <summary>

src/NodaTime.Serialization.SystemTextJson/NodaTimeDefaultJsonConverterFactory.cs

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,37 +34,35 @@ public NodaTimeDefaultJsonConverterFactory()
3434

3535
private static Dictionary<Type, JsonConverter> CreateConverterDictionary()
3636
{
37-
var converters = new Dictionary<Type, JsonConverter>()
38-
{
39-
{ typeof(AnnualDate), NodaConverters.AnnualDateConverter },
40-
{ typeof(AnnualDate?), CreateNullableConverter(NodaConverters.AnnualDateConverter) },
41-
{ typeof(DateInterval), NodaConverters.DateIntervalConverter },
42-
{ typeof(DateTimeZone), NodaConverters.CreateDateTimeZoneConverter(DateTimeZoneProviders.Tzdb) },
43-
{ typeof(Duration), NodaConverters.DurationConverter },
44-
{ typeof(Duration?), CreateNullableConverter((JsonConverter<Duration>) NodaConverters.DurationConverter) },
45-
{ typeof(Instant), NodaConverters.InstantConverter },
46-
{ typeof(Instant?), CreateNullableConverter(NodaConverters.InstantConverter) },
47-
{ typeof(Interval), NodaConverters.IntervalConverter },
48-
{ typeof(Interval?), CreateNullableConverter(NodaConverters.IntervalConverter) },
49-
{ typeof(LocalDate), NodaConverters.LocalDateConverter },
50-
{ typeof(LocalDate?), CreateNullableConverter(NodaConverters.LocalDateConverter) },
51-
{ typeof(LocalDateTime), NodaConverters.LocalDateTimeConverter },
52-
{ typeof(LocalDateTime?), CreateNullableConverter(NodaConverters.LocalDateTimeConverter) },
53-
{ typeof(LocalTime), NodaConverters.LocalTimeConverter },
54-
{ typeof(LocalTime?), CreateNullableConverter(NodaConverters.LocalTimeConverter) },
55-
{ typeof(Offset), NodaConverters.OffsetConverter },
56-
{ typeof(Offset?), CreateNullableConverter(NodaConverters.OffsetConverter) },
57-
{ typeof(OffsetDate), NodaConverters.OffsetDateConverter },
58-
{ typeof(OffsetDate?), CreateNullableConverter(NodaConverters.OffsetDateConverter) },
59-
{ typeof(OffsetDateTime), NodaConverters.OffsetDateTimeConverter },
60-
{ typeof(OffsetDateTime?), CreateNullableConverter(NodaConverters.OffsetDateTimeConverter) },
61-
{ typeof(OffsetTime), NodaConverters.OffsetTimeConverter },
62-
{ typeof(OffsetTime?), CreateNullableConverter(NodaConverters.OffsetTimeConverter) },
63-
{ typeof(Period), NodaConverters.RoundtripPeriodConverter },
64-
{ typeof(ZonedDateTime), NodaConverters.CreateZonedDateTimeConverter(DateTimeZoneProviders.Tzdb) },
65-
{ typeof(ZonedDateTime?), CreateNullableConverter(NodaConverters.CreateZonedDateTimeConverter(DateTimeZoneProviders.Tzdb)) }
66-
};
37+
var converters = new Dictionary<Type, JsonConverter>();
38+
39+
// Value types first, using the local function below to handle nullability.
40+
Add(NodaConverters.AnnualDateConverter);
41+
Add(NodaConverters.DurationConverterImpl);
42+
Add(NodaConverters.InstantConverter);
43+
Add(NodaConverters.IntervalConverter);
44+
Add(NodaConverters.LocalDateConverter);
45+
Add(NodaConverters.LocalDateTimeConverter);
46+
Add(NodaConverters.LocalTimeConverter);
47+
Add(NodaConverters.OffsetConverter);
48+
Add(NodaConverters.OffsetDateConverter);
49+
Add(NodaConverters.OffsetDateTimeConverter);
50+
Add(NodaConverters.OffsetTimeConverter);
51+
Add(NodaConverters.CreateZonedDateTimeConverter(DateTimeZoneProviders.Tzdb));
52+
53+
// Reference types
54+
converters[typeof(DateInterval)] = NodaConverters.DateIntervalConverter;
55+
converters[typeof(DateTimeZone)] = NodaConverters.CreateDateTimeZoneConverter(DateTimeZoneProviders.Tzdb);
56+
converters[typeof(Period)] = NodaConverters.RoundtripPeriodConverter;
6757
return converters;
58+
59+
// Adds the converter for a value type to the dictionary,
60+
// and a nullable converter for the corresponding nullable value type.
61+
void Add<T>(JsonConverter<T> converter) where T : struct
62+
{
63+
converters[typeof(T)] = converter;
64+
converters[typeof(T?)] = new NodaNullableConverter<T>(converter);
65+
}
6866
}
6967

7068
/// <summary>
@@ -81,10 +79,4 @@ internal static JsonConverter GetConverter(Type typeToConvert) =>
8179
/// <inheritdoc />
8280
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
8381
GetConverter(typeToConvert);
84-
85-
/// <summary>
86-
/// Helper to construct a <see cref="NodaNullableConverter{T}"/> with generic type inference at the call site.
87-
/// </summary>
88-
private static NodaNullableConverter<T> CreateNullableConverter<T>(JsonConverter<T> innerConverter) where T : struct
89-
=> new NodaNullableConverter<T>(innerConverter);
9082
}

0 commit comments

Comments
 (0)