diff --git a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/JsonSerializeToDictionary.csproj b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/JsonSerializeToDictionary.csproj index ad9f144d84..a4f71f9f34 100644 --- a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/JsonSerializeToDictionary.csproj +++ b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/JsonSerializeToDictionary.csproj @@ -2,13 +2,13 @@ Exe - net7.0 + net10.0 enable enable - + diff --git a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/Program.cs b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/Program.cs index 1bebe7d344..306fc7796f 100644 --- a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/Program.cs +++ b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionary/Program.cs @@ -64,4 +64,38 @@ WriteIndented = true }); Console.WriteLine(systemJsonComplex); +Console.WriteLine(); + +// Using System.Text.Json with a converter for the key type only +Console.WriteLine("============ Complex Dictionary: System.Text.Json w/ Key Converter ============"); +var systemJsonKeyConverter = JsonSerializer.Serialize(invoicesByCustomer, new JsonSerializerOptions +{ + Converters = { new CustomerKeyConverter() }, + WriteIndented = true +}); +Console.WriteLine(systemJsonKeyConverter); +Console.WriteLine(); + +// Using System.Text.Json after projecting the keys to Guid +Console.WriteLine("============ Complex Dictionary: System.Text.Json w/ Guid Keys ============"); +var invoicesByCustomerId = invoicesByCustomer.ToDictionary(pair => pair.Key.CustomerId, pair => pair.Value); +var systemJsonGuidKeys = JsonSerializer.Serialize(invoicesByCustomerId, new JsonSerializerOptions +{ + WriteIndented = true +}); +Console.WriteLine(systemJsonGuidKeys); +Console.WriteLine(); + +// Using System.Text.Json with a naming policy for the keys +Console.WriteLine("============ System.Text.Json - camelCase Keys ============"); +var stockByProduct = new Dictionary +{ + {"AppleCount", 3}, + {"OrangeCount", 5} +}; +var systemJsonCamelCaseKeys = JsonSerializer.Serialize(stockByProduct, new JsonSerializerOptions +{ + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase +}); +Console.WriteLine(systemJsonCamelCaseKeys); Console.WriteLine(); \ No newline at end of file diff --git a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/CustomerKeyConverter.cs b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/CustomerKeyConverter.cs new file mode 100644 index 0000000000..5ecf6448c9 --- /dev/null +++ b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/CustomerKeyConverter.cs @@ -0,0 +1,21 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace JsonSerializeToDictionaryDataModel; + +public sealed class CustomerKeyConverter : JsonConverter +{ + public override Customer Read(ref Utf8JsonReader reader, Type typeToConvert, + JsonSerializerOptions options) + { + // Since we are only dealing with Serializing in this article, we don't need to implement the Read method + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, Customer value, JsonSerializerOptions options) + => writer.WriteStringValue($"Customer-{value.CustomerId:N}"); + + public override void WriteAsPropertyName(Utf8JsonWriter writer, Customer value, + JsonSerializerOptions options) + => writer.WritePropertyName($"Customer-{value.CustomerId:N}"); +} diff --git a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/JsonSerializeToDictionaryDataModel.csproj b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/JsonSerializeToDictionaryDataModel.csproj index 69954a37c1..dde396945a 100644 --- a/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/JsonSerializeToDictionaryDataModel.csproj +++ b/json-csharp/JsonSerializeDictionary/src/JsonSerializeToDictionaryDataModel/JsonSerializeToDictionaryDataModel.csproj @@ -1,13 +1,13 @@ - net7.0 + net10.0 enable enable - + \ No newline at end of file diff --git a/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/CustomerKeyConverterUnitTest.cs b/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/CustomerKeyConverterUnitTest.cs new file mode 100644 index 0000000000..9c04941787 --- /dev/null +++ b/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/CustomerKeyConverterUnitTest.cs @@ -0,0 +1,31 @@ +using System.Text.Json; + +namespace JsonSerializeToDictionaryDataModel.Tests; + +public class CustomerKeyConverterUnitTest +{ + private static readonly Customer Customer = new( + "123 Nowhere Street, Fakeville, MD", + "555-555-0001", + new Person("John", "Smith"), + Guid.Parse("bfafbb48-f670-4e0e-87f6-d44ac219cf7b")); + + [Fact] + public void GivenDictionaryWithCustomerKeys_WhenSerializedWithoutConverter_ThenThrowsNotSupportedException() + { + var dictionary = new Dictionary { { Customer, 2 } }; + + Assert.Throws(() => JsonSerializer.Serialize(dictionary)); + } + + [Fact] + public void GivenDictionaryWithCustomerKeys_WhenSerializedWithKeyConverter_ThenKeyIsCustomerId() + { + var dictionary = new Dictionary { { Customer, 2 } }; + var options = new JsonSerializerOptions { Converters = { new CustomerKeyConverter() } }; + + var result = JsonSerializer.Serialize(dictionary, options); + + Assert.Equal("{\"Customer-bfafbb48f6704e0e87f6d44ac219cf7b\":2}", result); + } +} diff --git a/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/JsonSerializeToDictionaryDataModel.Tests.csproj b/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/JsonSerializeToDictionaryDataModel.Tests.csproj index f195456205..72bf56e2bc 100644 --- a/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/JsonSerializeToDictionaryDataModel.Tests.csproj +++ b/json-csharp/JsonSerializeDictionary/test/JsonSerializeToDictionaryDataModel.Tests/JsonSerializeToDictionaryDataModel.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net10.0 enable enable @@ -10,15 +10,15 @@ - - - - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all