k3davis
k3davis

Reputation: 1105

Prevent serialization if value is null or whitespace in JSON.NET

I have an object that needs to be serialized in such a way that both null and "whitespace" (empty or just spaces) values are not serialized. I don't control the object itself and therefore can't set attributes, but I know that all the properties are strings. Setting NullValueHandling to Ignore obviously only gets me part of the way to the solution.

It "seems" (as best I understand) like what I need to do is create a custom DefaultContractResolver but I haven't come up with a solution that works. Here are a couple failed attempts, for reference, that throw no exceptions but have no obvious effect on the serialization either:

public class NoNullWhiteSpaceResolver : DefaultContractResolver
{
    public static readonly NoNullWhiteSpaceResolver Instance = new NoNullWhiteSpaceResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        /* this doesn't work either
        if (property.ValueProvider.GetValue(member) == null ||
            (property.PropertyType == typeof(string) &&
            string.IsNullOrWhiteSpace((string)property.ValueProvider.GetValue(member))))
        {
            property.ShouldSerialize = i => false;
        }*/

        if (property.PropertyType == typeof(string))
        {
            property.ShouldSerialize =
                instance =>
                {
                    try
                    {
                        string s = (string) instance;
                        bool shouldSkip = string.IsNullOrWhiteSpace(s);
                        return !string.IsNullOrWhiteSpace(s);
                    }
                    catch
                    {
                        return true;
                    }
                };
        }

        return property;
    }
}

I'm implementing the resolver by

string str = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
{
    Formatting = Formatting.None;
    ContractResolver = new NoNullWhiteSpaceResolver();
});

Maybe I'm going about this backward but I appreciate any insights people have. I've worked around the issue by using an extension method/reflection to iterate over the properties of the object and setting the value to null if it's "nullorwhitespace" and then using the standard NullValueHandling but I'm hoping I can find a way to configure all of this in the serialization.

Upvotes: 3

Views: 2480

Answers (1)

stuartd
stuartd

Reputation: 73253

This seems to work:

public class NoNullWhiteSpaceResolver : DefaultContractResolver {
    public static readonly NoNullWhiteSpaceResolver Instance = new NoNullWhiteSpaceResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (property.PropertyType == typeof(string)) {
            property.ShouldSerialize =
                instance => {
                    try {
                        var rawValue = property.ValueProvider.GetValue(instance);
                        if (rawValue == null) {
                            return false;
                        }

                        string stringValue = property.ValueProvider.GetValue(instance).ToString();
                        return !string.IsNullOrWhiteSpace(stringValue);
                    }
                    catch {
                        return true;
                    }
                };
        }

        return property;
    }
}

Using this test class:

public class TestClass {
    public string WhiteSpace => "      ";
    public string Null = null;
    public string Empty = string.Empty;
    public string Value = "value";
}

This is the output:

{"Value":"value"}

Upvotes: 4

Related Questions