Skip to content

Commit 5def944

Browse files
committed
Generic JSON serializers instead of generated.
1 parent 6b8ae0d commit 5def944

File tree

8 files changed

+231
-230
lines changed

8 files changed

+231
-230
lines changed

DomainModeling.Generator/IdentityGenerator.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,11 @@ namespace {containingNamespace}
401401
{summary}
402402
403403
{(existingComponents.HasFlags(IdTypeComponents.SystemTextJsonConverter) ? "/*" : "")}
404-
{JsonSerializationGenerator.WriteJsonConverterAttribute(idTypeName)}
404+
{JsonSerializationGenerator.WriteJsonConverterAttribute(idTypeName, underlyingTypeFullyQualifiedName, numericAsString: underlyingTypeIsNumericUnsuitableForJson)}
405405
{(existingComponents.HasFlags(IdTypeComponents.SystemTextJsonConverter) ? "*/" : "")}
406406
407407
{(existingComponents.HasFlags(IdTypeComponents.NewtonsoftJsonConverter) ? "/*" : "")}
408-
{JsonSerializationGenerator.WriteNewtonsoftJsonConverterAttribute(idTypeName)}
408+
{JsonSerializationGenerator.WriteNewtonsoftJsonConverterAttribute(idTypeName, underlyingTypeFullyQualifiedName, numericAsString: underlyingTypeIsNumericUnsuitableForJson)}
409409
{(existingComponents.HasFlags(IdTypeComponents.NewtonsoftJsonConverter) ? "*/" : "")}
410410
411411
{(hasIdentityValueObjectAttribute ? "" : $"[IdentityValueObject<{underlyingTypeFullyQualifiedName}>]")}
@@ -606,14 +606,6 @@ public static bool TryParse(ReadOnlySpan<byte> utf8Text, IFormatProvider? provid
606606
#endif
607607
608608
#endregion
609-
610-
{(existingComponents.HasFlags(IdTypeComponents.SystemTextJsonConverter) ? "/*" : "")}
611-
{JsonSerializationGenerator.WriteJsonConverter(idTypeName, underlyingTypeFullyQualifiedName, numericAsString: underlyingTypeIsNumericUnsuitableForJson)}
612-
{(existingComponents.HasFlags(IdTypeComponents.SystemTextJsonConverter) ? "*/" : "")}
613-
614-
{(existingComponents.HasFlags(IdTypeComponents.NewtonsoftJsonConverter) ? "/*" : "")}
615-
{JsonSerializationGenerator.WriteNewtonsoftJsonConverter(idTypeName, underlyingTypeFullyQualifiedName, isStruct: true, numericAsString: underlyingTypeIsNumericUnsuitableForJson)}
616-
{(existingComponents.HasFlags(IdTypeComponents.NewtonsoftJsonConverter) ? "*/" : "")}
617609
}}
618610
}}
619611
";

DomainModeling.Generator/JsonSerializationGenerator.cs

Lines changed: 6 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -5,150 +5,15 @@ namespace Architect.DomainModeling.Generator;
55
/// </summary>
66
internal static class JsonSerializationGenerator
77
{
8-
public static string WriteJsonConverterAttribute(string modelTypeName)
8+
public static string WriteJsonConverterAttribute(string modelTypeName, string underlyingTypeFullyQualifiedName,
9+
bool numericAsString = false)
910
{
10-
return $"[System.Text.Json.Serialization.JsonConverter(typeof({modelTypeName}.JsonConverter))]";
11+
return $"[System.Text.Json.Serialization.JsonConverter(typeof({(numericAsString ? "LargeNumber" : "")}WrapperJsonConverter<{modelTypeName}, {underlyingTypeFullyQualifiedName}>))]";
1112
}
1213

13-
public static string WriteNewtonsoftJsonConverterAttribute(string modelTypeName)
14+
public static string WriteNewtonsoftJsonConverterAttribute(string modelTypeName, string underlyingTypeFullyQualifiedName,
15+
bool numericAsString = false)
1416
{
15-
return $"[Newtonsoft.Json.JsonConverter(typeof({modelTypeName}.NewtonsoftJsonConverter))]";
16-
}
17-
18-
public static string WriteJsonConverter(
19-
string modelTypeName, string underlyingTypeFullyQualifiedName,
20-
bool numericAsString)
21-
{
22-
var result = $@"
23-
#if NET7_0_OR_GREATER
24-
private sealed class JsonConverter : System.Text.Json.Serialization.JsonConverter<{modelTypeName}>
25-
{{
26-
public override {modelTypeName} Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) =>{(numericAsString
27-
? $@"
28-
// The longer numeric types are not JavaScript-safe, so treat them as strings
29-
DomainObjectSerializer.Deserialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(reader.TokenType == System.Text.Json.JsonTokenType.String
30-
? reader.GetParsedString<{underlyingTypeFullyQualifiedName}>(System.Globalization.CultureInfo.InvariantCulture)
31-
: System.Text.Json.JsonSerializer.Deserialize<{underlyingTypeFullyQualifiedName}>(ref reader, options));
32-
"
33-
: $@"
34-
DomainObjectSerializer.Deserialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(System.Text.Json.JsonSerializer.Deserialize<{underlyingTypeFullyQualifiedName}>(ref reader, options)!);
35-
")}
36-
37-
public override void Write(System.Text.Json.Utf8JsonWriter writer, {modelTypeName} value, System.Text.Json.JsonSerializerOptions options) =>{(numericAsString
38-
? $@"
39-
// The longer numeric types are not JavaScript-safe, so treat them as strings
40-
writer.WriteStringValue(DomainObjectSerializer.Serialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(value).Format(stackalloc char[64], ""0.#"", System.Globalization.CultureInfo.InvariantCulture));
41-
"
42-
: $@"
43-
System.Text.Json.JsonSerializer.Serialize(writer, DomainObjectSerializer.Serialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(value), options);
44-
")}
45-
46-
public override {modelTypeName} ReadAsPropertyName(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) =>
47-
DomainObjectSerializer.Deserialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(
48-
((System.Text.Json.Serialization.JsonConverter<{underlyingTypeFullyQualifiedName}>)options.GetConverter(typeof({underlyingTypeFullyQualifiedName}))).ReadAsPropertyName(ref reader, typeToConvert, options));
49-
50-
public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, {modelTypeName} value, System.Text.Json.JsonSerializerOptions options) =>
51-
((System.Text.Json.Serialization.JsonConverter<{underlyingTypeFullyQualifiedName}>)options.GetConverter(typeof({underlyingTypeFullyQualifiedName}))).WriteAsPropertyName(
52-
writer,
53-
DomainObjectSerializer.Serialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(value)!, options);
54-
}}
55-
#else
56-
private sealed class JsonConverter : System.Text.Json.Serialization.JsonConverter<{modelTypeName}>
57-
{{
58-
public override {modelTypeName} Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) =>{(numericAsString
59-
? $@"
60-
// The longer numeric types are not JavaScript-safe, so treat them as strings
61-
reader.TokenType == System.Text.Json.JsonTokenType.String
62-
? ({modelTypeName}){underlyingTypeFullyQualifiedName}.Parse(reader.GetString()!, System.Globalization.CultureInfo.InvariantCulture)
63-
: ({modelTypeName})System.Text.Json.JsonSerializer.Deserialize<{underlyingTypeFullyQualifiedName}>(ref reader, options);
64-
"
65-
: $@"
66-
({modelTypeName})System.Text.Json.JsonSerializer.Deserialize<{underlyingTypeFullyQualifiedName}>(ref reader, options)!;
67-
")}
68-
69-
public override void Write(System.Text.Json.Utf8JsonWriter writer, {modelTypeName} value, System.Text.Json.JsonSerializerOptions options) =>{(numericAsString
70-
? $@"
71-
// The longer numeric types are not JavaScript-safe, so treat them as strings
72-
writer.WriteStringValue(value.Value.ToString(""0.#"", System.Globalization.CultureInfo.InvariantCulture));
73-
"
74-
: $@"
75-
System.Text.Json.JsonSerializer.Serialize(writer, value.Value, options);
76-
")}
77-
}}
78-
#endif
79-
";
80-
81-
return result;
82-
}
83-
84-
public static string WriteNewtonsoftJsonConverter(
85-
string modelTypeName, string underlyingTypeFullyQualifiedName,
86-
bool isStruct, bool numericAsString)
87-
{
88-
var result = $@"
89-
#if NET7_0_OR_GREATER
90-
private sealed class NewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter
91-
{{
92-
public override bool CanConvert(Type objectType) =>
93-
objectType == typeof({modelTypeName}){(isStruct ? $" || objectType == typeof({modelTypeName}?)" : "")};
94-
95-
public override object? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) =>{(numericAsString
96-
? $@"
97-
// The longer numeric types are not JavaScript-safe, so treat them as strings
98-
reader.Value is null && objectType != typeof({modelTypeName}) // Null data for a nullable value type
99-
? ({modelTypeName}?)null
100-
: DomainObjectSerializer.Deserialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(reader.TokenType == Newtonsoft.Json.JsonToken.String
101-
? {underlyingTypeFullyQualifiedName}.Parse(serializer.Deserialize<string>(reader)!, System.Globalization.CultureInfo.InvariantCulture)
102-
: serializer.Deserialize<{underlyingTypeFullyQualifiedName}>(reader));
103-
"
104-
: $@"
105-
reader.Value is null && (!typeof({modelTypeName}).IsValueType || objectType != typeof({modelTypeName})) // Null data for a reference type or nullable value type
106-
? ({modelTypeName}?)null
107-
: DomainObjectSerializer.Deserialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(serializer.Deserialize<{underlyingTypeFullyQualifiedName}>(reader)!);
108-
")}
109-
110-
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) =>{(numericAsString
111-
? $@"
112-
// The longer numeric types are not JavaScript-safe, so treat them as strings
113-
serializer.Serialize(writer, value is not {modelTypeName} instance ? (object?)null : DomainObjectSerializer.Serialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(instance).ToString(""0.#"", System.Globalization.CultureInfo.InvariantCulture));
114-
"
115-
: $@"
116-
serializer.Serialize(writer, value is not {modelTypeName} instance ? (object?)null : DomainObjectSerializer.Serialize<{modelTypeName}, {underlyingTypeFullyQualifiedName}>(instance));
117-
")}
118-
}}
119-
#else
120-
private sealed class NewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter
121-
{{
122-
public override bool CanConvert(Type objectType) =>
123-
objectType == typeof({modelTypeName}){(isStruct ? $" || objectType == typeof({modelTypeName}?)" : "")};
124-
125-
public override object? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) =>{(numericAsString
126-
? $@"
127-
// The longer numeric types are not JavaScript-safe, so treat them as strings
128-
reader.Value is null && objectType != typeof({modelTypeName}) // Null data for a nullable value type
129-
? ({modelTypeName}?)null
130-
: reader.TokenType == Newtonsoft.Json.JsonToken.String
131-
? ({modelTypeName}){underlyingTypeFullyQualifiedName}.Parse(serializer.Deserialize<string>(reader)!, System.Globalization.CultureInfo.InvariantCulture)
132-
: ({modelTypeName})serializer.Deserialize<{underlyingTypeFullyQualifiedName}>(reader);
133-
"
134-
: $@"
135-
reader.Value is null && (!typeof({modelTypeName}).IsValueType || objectType != typeof({modelTypeName})) // Null data for a reference type or nullable value type
136-
? ({modelTypeName}?)null
137-
: ({modelTypeName})serializer.Deserialize<{underlyingTypeFullyQualifiedName}>(reader)!;
138-
")}
139-
140-
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) =>{(numericAsString
141-
? $@"
142-
// The longer numeric types are not JavaScript-safe, so treat them as strings
143-
serializer.Serialize(writer, value is not {modelTypeName} instance ? (object?)null : instance.Value.ToString(""0.#"", System.Globalization.CultureInfo.InvariantCulture));
144-
"
145-
: $@"
146-
serializer.Serialize(writer, value is not {modelTypeName} instance ? (object?)null : instance.Value);
147-
")}
148-
}}
149-
#endif
150-
";
151-
152-
return result;
17+
return $"[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft{(numericAsString ? "LargeNumber" : "")}WrapperJsonConverter<{modelTypeName}, {underlyingTypeFullyQualifiedName}>))]";
15318
}
15419
}

DomainModeling.Generator/WrapperValueObjectGenerator.cs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,11 @@ private static void GenerateSource(SourceProductionContext context, Generatable
337337
namespace {containingNamespace}
338338
{{
339339
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.SystemTextJsonConverter) ? "/*" : "")}
340-
{JsonSerializationGenerator.WriteJsonConverterAttribute(typeName)}
340+
{JsonSerializationGenerator.WriteJsonConverterAttribute(typeName, underlyingTypeFullyQualifiedName)}
341341
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.SystemTextJsonConverter) ? "*/" : "")}
342342
343343
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.NewtonsoftJsonConverter) ? "/*" : "")}
344-
{JsonSerializationGenerator.WriteNewtonsoftJsonConverterAttribute(typeName)}
344+
{JsonSerializationGenerator.WriteNewtonsoftJsonConverterAttribute(typeName, underlyingTypeFullyQualifiedName)}
345345
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.NewtonsoftJsonConverter) ? "*/" : "")}
346346
347347
/* Generated */ {generatable.Accessibility.ToCodeString()} sealed partial{(generatable.IsRecord ? " record" : "")} class {typeName}
@@ -569,14 +569,6 @@ public static bool TryParse(ReadOnlySpan<byte> utf8Text, IFormatProvider? provid
569569
#endif
570570
571571
#endregion
572-
573-
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.SystemTextJsonConverter) ? "/*" : "")}
574-
{JsonSerializationGenerator.WriteJsonConverter(typeName, underlyingTypeFullyQualifiedName, numericAsString: false)}
575-
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.SystemTextJsonConverter) ? "*/" : "")}
576-
577-
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.NewtonsoftJsonConverter) ? "/*" : "")}
578-
{JsonSerializationGenerator.WriteNewtonsoftJsonConverter(typeName, underlyingTypeFullyQualifiedName, isStruct: false, numericAsString: false)}
579-
{(existingComponents.HasFlags(WrapperValueObjectTypeComponents.NewtonsoftJsonConverter) ? "*/" : "")}
580572
}}
581573
}}
582574
";

DomainModeling.Tests/IdentityTests.cs

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -748,8 +748,8 @@ public bool TryFormat(Span<byte> utf8Destination, out int bytesWritten, ReadOnly
748748
/// Should merely compile.
749749
/// </summary>
750750
[IdentityValueObject<int>]
751-
[System.Text.Json.Serialization.JsonConverter(typeof(JsonConverter))]
752-
[Newtonsoft.Json.JsonConverter(typeof(NewtonsoftJsonConverter))]
751+
[System.Text.Json.Serialization.JsonConverter(typeof(WrapperJsonConverter<FullySelfImplementedIdentity, int>))]
752+
[Newtonsoft.Json.JsonConverter(typeof(NewtonsoftWrapperJsonConverter<FullySelfImplementedIdentity, int>))]
753753
internal readonly partial struct FullySelfImplementedIdentity
754754
: IIdentity<int>,
755755
IEquatable<FullySelfImplementedIdentity>,
@@ -872,38 +872,6 @@ public static FullySelfImplementedIdentity Parse(ReadOnlySpan<byte> utf8Text, IF
872872
#endif
873873

874874
#endregion
875-
876-
private sealed class JsonConverter : System.Text.Json.Serialization.JsonConverter<FullySelfImplementedIdentity>
877-
{
878-
public override FullySelfImplementedIdentity Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) =>
879-
DomainObjectSerializer.Deserialize<FullySelfImplementedIdentity, int>(System.Text.Json.JsonSerializer.Deserialize<int>(ref reader, options)!);
880-
881-
public override void Write(System.Text.Json.Utf8JsonWriter writer, FullySelfImplementedIdentity value, System.Text.Json.JsonSerializerOptions options) =>
882-
System.Text.Json.JsonSerializer.Serialize(writer, DomainObjectSerializer.Serialize<FullySelfImplementedIdentity, int>(value), options);
883-
884-
public override FullySelfImplementedIdentity ReadAsPropertyName(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) =>
885-
DomainObjectSerializer.Deserialize<FullySelfImplementedIdentity, int>(
886-
((System.Text.Json.Serialization.JsonConverter<int>)options.GetConverter(typeof(int))).ReadAsPropertyName(ref reader, typeToConvert, options));
887-
888-
public override void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, FullySelfImplementedIdentity value, System.Text.Json.JsonSerializerOptions options) =>
889-
((System.Text.Json.Serialization.JsonConverter<int>)options.GetConverter(typeof(int))).WriteAsPropertyName(
890-
writer,
891-
DomainObjectSerializer.Serialize<FullySelfImplementedIdentity, int>(value)!, options);
892-
}
893-
894-
private sealed class NewtonsoftJsonConverter : Newtonsoft.Json.JsonConverter
895-
{
896-
public override bool CanConvert(Type objectType) =>
897-
objectType == typeof(FullySelfImplementedIdentity) || objectType == typeof(FullySelfImplementedIdentity?);
898-
899-
public override object? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object? existingValue, Newtonsoft.Json.JsonSerializer serializer) =>
900-
reader.Value is null && (!typeof(FullySelfImplementedIdentity).IsValueType || objectType != typeof(FullySelfImplementedIdentity)) // Null data for a reference type or nullable value type
901-
? (FullySelfImplementedIdentity?)null
902-
: DomainObjectSerializer.Deserialize<FullySelfImplementedIdentity, int>(serializer.Deserialize<int>(reader)!);
903-
904-
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object? value, Newtonsoft.Json.JsonSerializer serializer) =>
905-
serializer.Serialize(writer, value is not FullySelfImplementedIdentity instance ? (object?)null : DomainObjectSerializer.Serialize<FullySelfImplementedIdentity, int>(instance));
906-
}
907875
}
908876
}
909877
}

0 commit comments

Comments
 (0)