diff --git a/ClassLibraries/Macross.Json.Extensions/Code/System.Text.Json.Serialization/JsonEmptyStringToNullConverter.cs b/ClassLibraries/Macross.Json.Extensions/Code/System.Text.Json.Serialization/JsonEmptyStringToNullConverter.cs new file mode 100644 index 0000000..beeb54d --- /dev/null +++ b/ClassLibraries/Macross.Json.Extensions/Code/System.Text.Json.Serialization/JsonEmptyStringToNullConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Macross.Json.Extensions.System.Text.Json.Serialization +{ + /// + /// to output empty strings as null values. + /// + public class JsonEmptyStringToNullConverter : JsonConverter + { + /// + public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => reader.GetString(); + + /// + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + { +#pragma warning disable CA1062 // Don't perform checks for performance. Trust our callers will be nice. + if (string.IsNullOrEmpty(value)) + writer.WriteNullValue(); + else + writer.WriteStringValue(value); +#pragma warning restore CA1062 // Validate arguments of public methods + } + } +} diff --git a/ClassLibraries/Macross.Json.Extensions/Test/JsonEmptyStringToNullConverterTests.cs b/ClassLibraries/Macross.Json.Extensions/Test/JsonEmptyStringToNullConverterTests.cs new file mode 100644 index 0000000..27e5728 --- /dev/null +++ b/ClassLibraries/Macross.Json.Extensions/Test/JsonEmptyStringToNullConverterTests.cs @@ -0,0 +1,73 @@ +using System.Text.Json; + +using Macross.Json.Extensions.System.Text.Json.Serialization; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Macross.Json.Extensions.Tests +{ + [TestClass] + public class JsonEmptyStringToNullConverterTests + { + private const string? NullString = null; + + [TestMethod] + public void TestNullIsOutputForEmptyString() + { + JsonSerializerOptions options = new JsonSerializerOptions(); + options.Converters.Add(new JsonEmptyStringToNullConverter()); + + string Json = JsonSerializer.Serialize("Test", options); + Assert.AreEqual(@"""Test""", Json); + + Json = JsonSerializer.Serialize(string.Empty, options); + Assert.AreEqual("null", Json); + + Json = JsonSerializer.Serialize(NullString, options); + Assert.AreEqual("null", Json); + + Json = JsonSerializer.Serialize(new TestClass(), options); + Assert.AreEqual("{\"Str1\":null,\"Str2\":null}", Json); + + Json = JsonSerializer.Serialize(new TestClass() { Str1 = "One" }, options); + Assert.AreEqual("{\"Str1\":\"One\",\"Str2\":null}", Json); + + Json = JsonSerializer.Serialize(new TestClass() { Str1 = "One", Str2 = "Two" }, options); + Assert.AreEqual("{\"Str1\":\"One\",\"Str2\":\"Two\"}", Json); + + Json = JsonSerializer.Serialize(new TestClass() { Str2 = "Two" }, options); + Assert.AreEqual("{\"Str1\":null,\"Str2\":\"Two\"}", Json); + + options = new JsonSerializerOptions(); + options.Converters.Add(new JsonEmptyStringToNullConverter()); + options.IgnoreNullValues = true; + + Json = JsonSerializer.Serialize("Test", options); + Assert.AreEqual(@"""Test""", Json); + + Json = JsonSerializer.Serialize(string.Empty, options); + Assert.AreEqual("null", Json); + + Json = JsonSerializer.Serialize(NullString, options); + Assert.AreEqual("null", Json); + + Json = JsonSerializer.Serialize(new TestClass(), options); + Assert.AreEqual("{}", Json); + + Json = JsonSerializer.Serialize(new TestClass() { Str1 = "One" }, options); + Assert.AreEqual("{\"Str1\":\"One\"}", Json); + + Json = JsonSerializer.Serialize(new TestClass() { Str1 = "One", Str2 = "Two" }, options); + Assert.AreEqual("{\"Str1\":\"One\",\"Str2\":\"Two\"}", Json); + + Json = JsonSerializer.Serialize(new TestClass() { Str2 = "Two" }, options); + Assert.AreEqual("{\"Str2\":\"Two\"}", Json); + } + + private class TestClass + { + public string? Str1 { get; set; } + + public string? Str2 { get; set; } + } + } +}