Skip to content

Commit

Permalink
Add a Converter to serialize empty strings as null values
Browse files Browse the repository at this point in the history
Allows these values to be excluded when `IgnoreNullValues` is True
  • Loading branch information
MatthewSteeples committed Aug 26, 2021
1 parent d38d4bb commit 5bc984f
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Macross.Json.Extensions.System.Text.Json.Serialization
{
/// <summary>
/// <see cref="JsonConverter"/> to output empty strings as null values.
/// </summary>
public class JsonEmptyStringToNullConverter : JsonConverter<string>
{
/// <inheritdoc/>
public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => reader.GetString();

/// <inheritdoc/>
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
}
}
}
Original file line number Diff line number Diff line change
@@ -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; }
}
}
}

0 comments on commit 5bc984f

Please sign in to comment.