diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.EnumAsString.Models/JsonSerialization.EnumAsString.Models.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.EnumAsString.Models/JsonSerialization.EnumAsString.Models.csproj index bafd05b116..9ed914b5ba 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.EnumAsString.Models/JsonSerialization.EnumAsString.Models.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.EnumAsString.Models/JsonSerialization.EnumAsString.Models.csproj @@ -1,9 +1,9 @@ - - - - net6.0 - enable - enable - - - + + + + net10.0 + enable + enable + + + diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/JsonSerialization.Native.EnumAsString.MinimalApi.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/JsonSerialization.Native.EnumAsString.MinimalApi.csproj index 561286c7ec..5f426b3d04 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/JsonSerialization.Native.EnumAsString.MinimalApi.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/JsonSerialization.Native.EnumAsString.MinimalApi.csproj @@ -1,19 +1,16 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - - + + + + net10.0 + enable + enable + + + + + + + + + + diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/Program.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/Program.cs index 7a1f4b6a0e..76b9a8c8fb 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/Program.cs +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApi/Program.cs @@ -1,16 +1,15 @@ -using JsonSerialization.EnumAsString.Models; -using Microsoft.AspNetCore.Http.Json; -using System.Text.Json.Serialization; - -var builder = WebApplication.CreateBuilder(args); -builder.Services.Configure(options => -{ - options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); -}); - -var app = builder.Build(); - -app.MapGet("/poster", () => Canvas.Poster); -app.MapGet("/schedule", () => new { Description = "Exhibition", Day = DayOfWeek.Monday }); - +using JsonSerialization.EnumAsString.Models; +using System.Text.Json.Serialization; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.ConfigureHttpJsonOptions(options => +{ + options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); +}); + +var app = builder.Build(); + +app.MapGet("/poster", () => Canvas.Poster); +app.MapGet("/schedule", () => new { Description = "Exhibition", Day = DayOfWeek.Monday }); + app.Run(); \ No newline at end of file diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApiTests/JsonSerialization.Native.EnumAsString.MinimalApiTests.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApiTests/JsonSerialization.Native.EnumAsString.MinimalApiTests.csproj index 51d9298a84..2e074adfb4 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApiTests/JsonSerialization.Native.EnumAsString.MinimalApiTests.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.MinimalApiTests/JsonSerialization.Native.EnumAsString.MinimalApiTests.csproj @@ -1,28 +1,27 @@  - net6.0 + net10.0 enable false - - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/JsonSerialization.Native.EnumAsString.WebApi.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/JsonSerialization.Native.EnumAsString.WebApi.csproj index 712497069a..45aca8b427 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/JsonSerialization.Native.EnumAsString.WebApi.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/JsonSerialization.Native.EnumAsString.WebApi.csproj @@ -1,18 +1,15 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - + + + + net10.0 + enable + enable + + + + + + + + + diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/Program.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/Program.cs index 231d6ed194..76b28f62bb 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/Program.cs +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsString.WebApi/Program.cs @@ -1,17 +1,15 @@ -using System.Text.Json.Serialization; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddControllers() - .AddJsonOptions(options => - { - options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); - }); - -var app = builder.Build(); - -app.UseAuthorization(); - -app.MapControllers(); - +using System.Text.Json.Serialization; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllers() + .AddJsonOptions(options => + { + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + }); + +var app = builder.Build(); + +app.MapControllers(); + app.Run(); \ No newline at end of file diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomNames/ToggleControl.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomNames/ToggleControl.cs new file mode 100644 index 0000000000..8b5cfd4651 --- /dev/null +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomNames/ToggleControl.cs @@ -0,0 +1,15 @@ +namespace JsonSerialization.Native.EnumAsStringTests.CustomNames; + +public record struct ToggleControl(string Name, ToggleType Type); + +public enum ToggleType +{ + [JsonStringEnumMemberName("Enable/Disable")] + EnableDisable, + + [JsonStringEnumMemberName("Visible/Hidden")] + VisibleHidden, + + [JsonStringEnumMemberName("Editable/Readonly")] + EditableReadonly, +} diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomSerializationUnitTest.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomSerializationUnitTest.cs index 3d7e3ea649..4d324b5bbd 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomSerializationUnitTest.cs +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/CustomSerializationUnitTest.cs @@ -1,44 +1,68 @@ -using JsonSerialization.EnumAsString.Models; - -namespace JsonSerialization.Native.EnumAsStringTests; - -public class CustomSerializationUnitTest : UnitTestBase -{ - [Fact] - public void GivenEnum_WhenSerializeWithPropertyCamelCasePolicy_ThenDoesNotCamelCaseEnumValues() - { - var options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - options.Converters.Add(new JsonStringEnumConverter()); - - var json = JsonSerializer.Serialize(Canvas.Poster, options); - - Assert.Equal("{\"name\":\"Poster\",\"backColor\":\"LightGray\",\"medium\":\"Water\",\"pen\":{\"name\":\"Simple\",\"color\":\"Red\"}}", json); - } - - [Fact] - public void GivenEnum_WhenSerializeWithEnumCamelCasePolicy_ThenCamelCaseEnumValues() - { - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); - - var json = JsonSerializer.Serialize(Canvas.Poster, options); - - Assert.Equal("{\"Name\":\"Poster\",\"BackColor\":\"lightGray\",\"Medium\":\"water\",\"Pen\":{\"Name\":\"Simple\",\"Color\":\"red\"}}", json); - } - - [Fact] - public void GivenEnum_WhenDecoratedWithEnumMember_ThenIgnoresEnumMemberOnSerialize() - { - var controls = new ToggleControl[] - { - new("toggle1", ToggleType.EnableDisable), - new("toggle2", ToggleType.VisibleHidden) - }; - var json = SerializeWithStringEnum(controls); - - Assert.Equal("[{\"Name\":\"toggle1\",\"Type\":\"EnableDisable\"},{\"Name\":\"toggle2\",\"Type\":\"VisibleHidden\"}]", json); - } -} \ No newline at end of file +using JsonSerialization.EnumAsString.Models; + +namespace JsonSerialization.Native.EnumAsStringTests; + +public class CustomSerializationUnitTest : UnitTestBase +{ + [Fact] + public void GivenEnum_WhenSerializeWithPropertyCamelCasePolicy_ThenDoesNotCamelCaseEnumValues() + { + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + options.Converters.Add(new JsonStringEnumConverter()); + + var json = JsonSerializer.Serialize(Canvas.Poster, options); + + Assert.Equal("{\"name\":\"Poster\",\"backColor\":\"LightGray\",\"medium\":\"Water\",\"pen\":{\"name\":\"Simple\",\"color\":\"Red\"}}", json); + } + + [Fact] + public void GivenEnum_WhenSerializeWithEnumCamelCasePolicy_ThenCamelCaseEnumValues() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); + + var json = JsonSerializer.Serialize(Canvas.Poster, options); + + Assert.Equal("{\"Name\":\"Poster\",\"BackColor\":\"lightGray\",\"Medium\":\"water\",\"Pen\":{\"Name\":\"Simple\",\"Color\":\"red\"}}", json); + } + + [Fact] + public void GivenEnum_WhenDecoratedWithEnumMember_ThenIgnoresEnumMemberOnSerialize() + { + var controls = new ToggleControl[] + { + new("toggle1", ToggleType.EnableDisable), + new("toggle2", ToggleType.VisibleHidden) + }; + var json = SerializeWithStringEnum(controls); + + Assert.Equal("[{\"Name\":\"toggle1\",\"Type\":\"EnableDisable\"},{\"Name\":\"toggle2\",\"Type\":\"VisibleHidden\"}]", json); + } + + [Fact] + public void GivenEnum_WhenDecoratedWithJsonStringEnumMemberName_ThenSerializeAsSpecifiedString() + { + var controls = new CustomNames.ToggleControl[] + { + new("toggle1", CustomNames.ToggleType.EnableDisable), + new("toggle2", CustomNames.ToggleType.VisibleHidden) + }; + + var json = SerializeWithStringEnum(controls); + + Assert.Equal("[{\"Name\":\"toggle1\",\"Type\":\"Enable/Disable\"},{\"Name\":\"toggle2\",\"Type\":\"Visible/Hidden\"}]", json); + } + + [Fact] + public void GivenEnum_WhenDecoratedWithJsonStringEnumMemberNameButNoConverterRegistered_ThenSerializeAsNumber() + { + var control = new CustomNames.ToggleControl("toggle1", CustomNames.ToggleType.EnableDisable); + + var json = Serialize(control); + + Assert.Equal("{\"Name\":\"toggle1\",\"Type\":0}", json); + } +} diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/DataContract/DataContractJsonSerializationUnitTest.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/DataContract/DataContractJsonSerializationUnitTest.cs new file mode 100644 index 0000000000..7d4679bd6c --- /dev/null +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/DataContract/DataContractJsonSerializationUnitTest.cs @@ -0,0 +1,81 @@ +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Text; + +namespace JsonSerialization.Native.EnumAsStringTests.DataContract; + +public class DataContractJsonSerializationUnitTest +{ + private static string SerializeToJson(ToggleSet set) + { + var serializer = new DataContractJsonSerializer(typeof(ToggleSet)); + + using var stream = new MemoryStream(); + serializer.WriteObject(stream, set); + + return Encoding.UTF8.GetString(stream.ToArray()); + } + + private static ToggleSet? DeserializeFromJson(string json) + { + var serializer = new DataContractJsonSerializer(typeof(ToggleSet)); + + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)); + + return serializer.ReadObject(stream) as ToggleSet; + } + + [Fact] + public void GivenEnum_WhenSerializedWithDataContractJsonSerializer_ThenWritesNumbersAndIgnoresEnumMember() + { + var set = new ToggleSet + { + Decorated = ToggleState.EnableDisable, + Undecorated = ToggleState.VisibleHidden + }; + + var json = SerializeToJson(set); + + Assert.Equal("{\"Decorated\":0,\"Undecorated\":1}", json); + } + + [Fact] + public void GivenEnumMemberString_WhenDeserializedWithDataContractJsonSerializer_ThenThrows() + { + var json = "{\"Decorated\":\"Enable/Disable\",\"Undecorated\":1}"; + + var exception = Assert.Throws(() => DeserializeFromJson(json)); + + Assert.Contains("cannot be parsed as the type 'Int64'", exception.Message); + } + + [Fact] + public void GivenUndefinedNumber_WhenDeserializedWithDataContractJsonSerializer_ThenAcceptsIt() + { + var json = "{\"Decorated\":42,\"Undecorated\":1}"; + + var set = DeserializeFromJson(json); + + Assert.NotNull(set); + Assert.Equal(42, (int)set.Decorated); + } + + [Fact] + public void GivenSameEnum_WhenSerializedWithXmlDataContractSerializer_ThenHonoursEnumMember() + { + var set = new ToggleSet + { + Decorated = ToggleState.EnableDisable, + Undecorated = ToggleState.VisibleHidden + }; + var serializer = new DataContractSerializer(typeof(ToggleSet)); + + using var stream = new MemoryStream(); + serializer.WriteObject(stream, set); + var xml = Encoding.UTF8.GetString(stream.ToArray()); + + Assert.Contains("Enable/Disable", xml); + Assert.Contains("Visible/Hidden", xml); + } +} diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/DataContract/ToggleState.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/DataContract/ToggleState.cs new file mode 100644 index 0000000000..68e9899cf9 --- /dev/null +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/DataContract/ToggleState.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; + +namespace JsonSerialization.Native.EnumAsStringTests.DataContract; + +[DataContract] +public class ToggleSet +{ + [DataMember] + public ToggleState Decorated { get; set; } + + [DataMember] + public ToggleState Undecorated { get; set; } +} + +[DataContract] +public enum ToggleState +{ + [EnumMember(Value = "Enable/Disable")] + EnableDisable = 0, + + [EnumMember(Value = "Visible/Hidden")] + VisibleHidden = 1, +} diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/JsonSerialization.Native.EnumAsStringTests.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/JsonSerialization.Native.EnumAsStringTests.csproj index 43cb356837..24f1ecd1d1 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/JsonSerialization.Native.EnumAsStringTests.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/JsonSerialization.Native.EnumAsStringTests.csproj @@ -1,29 +1,28 @@  - net6.0 + net10.0 enable false - - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - - + + + diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/SourceGeneration/CanvasContext.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/SourceGeneration/CanvasContext.cs new file mode 100644 index 0000000000..26ab806ea0 --- /dev/null +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/SourceGeneration/CanvasContext.cs @@ -0,0 +1,7 @@ +using JsonSerialization.EnumAsString.Models; + +namespace JsonSerialization.Native.EnumAsStringTests.SourceGeneration; + +[JsonSourceGenerationOptions(UseStringEnumConverter = true)] +[JsonSerializable(typeof(Canvas))] +internal partial class CanvasContext : JsonSerializerContext; diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/SourceGeneration/SourceGenerationUnitTest.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/SourceGeneration/SourceGenerationUnitTest.cs new file mode 100644 index 0000000000..4ae1ac2d2e --- /dev/null +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Native.EnumAsStringTests/SourceGeneration/SourceGenerationUnitTest.cs @@ -0,0 +1,14 @@ +using JsonSerialization.EnumAsString.Models; + +namespace JsonSerialization.Native.EnumAsStringTests.SourceGeneration; + +public class SourceGenerationUnitTest +{ + [Fact] + public void GivenSourceGeneratedContext_WhenUseStringEnumConverterIsSet_ThenSerializeAllEnumsAsString() + { + var json = JsonSerializer.Serialize(Canvas.Poster, CanvasContext.Default.Canvas); + + Assert.Equal("{\"Name\":\"Poster\",\"BackColor\":\"LightGray\",\"Medium\":\"Water\",\"Pen\":{\"Name\":\"Simple\",\"Color\":\"Red\"}}", json); + } +} diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/JsonSerialization.Newtonsoft.EnumAsString.WebApi.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/JsonSerialization.Newtonsoft.EnumAsString.WebApi.csproj index 41141b26de..3cb1acf083 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/JsonSerialization.Newtonsoft.EnumAsString.WebApi.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/JsonSerialization.Newtonsoft.EnumAsString.WebApi.csproj @@ -1,20 +1,20 @@ - - - - net6.0 - enable - enable - - - - - - - - - - - - - - + + + + net10.0 + enable + enable + + + + + + + + + + + + + + diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/Program.cs b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/Program.cs index 69d58e46a3..6872f87b11 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/Program.cs +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsString.WebApi/Program.cs @@ -1,17 +1,15 @@ -using Newtonsoft.Json.Converters; - -var builder = WebApplication.CreateBuilder(args); - -builder.Services.AddControllers() - .AddNewtonsoftJson(options => - { - options.SerializerSettings.Converters.Add(new StringEnumConverter()); - }); - -var app = builder.Build(); - -app.UseAuthorization(); - -app.MapControllers(); - +using Newtonsoft.Json.Converters; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllers() + .AddNewtonsoftJson(options => + { + options.SerializerSettings.Converters.Add(new StringEnumConverter()); + }); + +var app = builder.Build(); + +app.MapControllers(); + app.Run(); \ No newline at end of file diff --git a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsStringTests/JsonSerialization.Newtonsoft.EnumAsStringTests.csproj b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsStringTests/JsonSerialization.Newtonsoft.EnumAsStringTests.csproj index fd8d34002a..864cf3aa02 100644 --- a/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsStringTests/JsonSerialization.Newtonsoft.EnumAsStringTests.csproj +++ b/json-csharp/JsonSerializationOfEnumAsString/JsonSerialization.Newtonsoft.EnumAsStringTests/JsonSerialization.Newtonsoft.EnumAsStringTests.csproj @@ -1,28 +1,28 @@ - - - - net6.0 - enable - false - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - + + + + net10.0 + enable + false + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + +