diff --git a/CHANGELOG.md b/CHANGELOG.md index e97987f4..48debfd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ Represents the **NuGet** versions. - *Enhancement*: Upgraded `UnitTestEx` dependency to `4.0.2` to enable _isolated_ function testing. - *Enhancement*: Enabled `IJsonSerializer` support for `CompositeKey` JSON serialization/deserialization. - *Enhancement*: Added `IEventDataFormatter` which when implemented by the value set as the `EventData.Value` allows additional formatting to be applied by the `EventDataFormatter`. -- *Fixed*: `EventDataFormatter` and `CloudEventSerializerBase` updated to correctly set the `Key` where applicable. +- *Fixed*: Added `ReferenceDataMultiDictionaryConverterFactory` to ensure each `IReferenceDataCollection` is serialized correctly according to its underlying type. +- *Fixed*: `EventDataFormatter` and `CloudEventSerializerBase` updated to correctly set the `Key` property where applicable. - *Internal:* Upgraded `NUnit` dependency to `4.0.1` for all `CoreEx` unit test; also, all unit tests now leverage the [_NUnit constraint model_](https://docs.nunit.org/articles/nunit/writing-tests/assertions/assertion-models/constraint.html) testing approach. ## v3.8.1 diff --git a/samples/My.Hr/My.Hr.UnitTest/ReferenceDataControllerTest.cs b/samples/My.Hr/My.Hr.UnitTest/ReferenceDataControllerTest.cs index 76509784..f9cdde52 100644 --- a/samples/My.Hr/My.Hr.UnitTest/ReferenceDataControllerTest.cs +++ b/samples/My.Hr/My.Hr.UnitTest/ReferenceDataControllerTest.cs @@ -94,7 +94,7 @@ public void C100_Named() using var test = ApiTester.Create().UseJsonSerializer(new ReferenceDataContentJsonSerializer().ToUnitTestEx()); var r = test.Controller() - .Run(c => c.GetNamed(), new HttpRequestOptions { UrlQueryString = "gender&usstate" }) + .Run(c => c.GetNamed(), requestOptions: new HttpRequestOptions { UrlQueryString = "gender&usstate" }) .AssertOK(); } } diff --git a/src/CoreEx/Text/Json/ReferenceDataContentJsonSerializer.cs b/src/CoreEx/Text/Json/ReferenceDataContentJsonSerializer.cs index 41f0b3e5..ce5acc5a 100644 --- a/src/CoreEx/Text/Json/ReferenceDataContentJsonSerializer.cs +++ b/src/CoreEx/Text/Json/ReferenceDataContentJsonSerializer.cs @@ -23,7 +23,7 @@ public class ReferenceDataContentJsonSerializer(Stj.JsonSerializerOptions? optio /// = false /// = . /// = . - /// = , , and . + /// = , , , and . /// /// public static new Stj.JsonSerializerOptions DefaultOptions { get; set; } = new Stj.JsonSerializerOptions(Stj.JsonSerializerDefaults.Web) @@ -32,7 +32,7 @@ public class ReferenceDataContentJsonSerializer(Stj.JsonSerializerOptions? optio WriteIndented = false, DictionaryKeyPolicy = SubstituteNamingPolicy.Substitute, PropertyNamingPolicy = SubstituteNamingPolicy.Substitute, - Converters = { new JsonStringEnumConverter(), new ExceptionConverterFactory(), new CollectionResultConverterFactory(), new ResultConverterFactory() } + Converters = { new JsonStringEnumConverter(), new ExceptionConverterFactory(), new CollectionResultConverterFactory(), new ResultConverterFactory(), new ReferenceDataMultiDictionaryConverterFactory() } }; } } \ No newline at end of file diff --git a/src/CoreEx/Text/Json/ReferenceDataMultiDictionaryConverterFactory.cs b/src/CoreEx/Text/Json/ReferenceDataMultiDictionaryConverterFactory.cs new file mode 100644 index 00000000..b726a23b --- /dev/null +++ b/src/CoreEx/Text/Json/ReferenceDataMultiDictionaryConverterFactory.cs @@ -0,0 +1,45 @@ +// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/CoreEx + +using CoreEx.RefData; +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace CoreEx.Text.Json +{ + /// + /// Performs JSON value conversion for values. + /// + /// This is required to ensure each is serialized correctly according to its underlying type. + public class ReferenceDataMultiDictionaryConverterFactory : JsonConverterFactory + { + /// + public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(ReferenceDataMultiDictionary); + + /// + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) => new ReferenceDataMultiDictionaryConverter(); + + /// + /// Performs the "actual" JSON value conversion for values. + /// + private class ReferenceDataMultiDictionaryConverter : JsonConverter + { + /// + public override ReferenceDataMultiDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotSupportedException($"Deserialization of Type {nameof(ReferenceDataMultiDictionary)} is not supported."); + + /// + public override void Write(Utf8JsonWriter writer, ReferenceDataMultiDictionary value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + + foreach (var kvp in value) + { + writer.WritePropertyName(options.DictionaryKeyPolicy?.ConvertName(kvp.Key) ?? kvp.Key); + System.Text.Json.JsonSerializer.Serialize(writer, kvp.Value, kvp.Value.GetType(), options); + } + + writer.WriteEndObject(); + } + } + } +} \ No newline at end of file