The other day I wanted to use Newtonsoft JSON serializer to convert objects to JSON strings, with the twist that if some property of the object was null it should be defaulted to a specific value in the JSON string.

There is the DefaultValueAttribute but that seems to work only for deserialization (or so it seemed when I gave up searching for an out of the box behavior).

It turns out you can implement a ContractResolver. Inheriting from the base DefaultContractResolver seems to be the easiest way to go. Then you can override just the CreateProperty method and provide an instance of IValueProvider to the property contract generated by that method. Check out the example below.

This would be the override of the CreateProperty method in your ContractResolver.

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
    var defaultValue = /* your logic here to resolve default values */;
    var property = base.CreateProperty(member, memberSerialization);
    property.ValueProvider = new DefaultValueProvider(property.ValueProvider, defaultValue);
}

And this an example of a dummy IValueProvider.

private class DefaultValueProvider : IValueProvider
{
    private IValueProvider provider;
    private object defaultValue;

    public DefaultValueProvider(IValueProvider provider, object defaultValue)
    {
        this.provider = provider;
        this.defaultValue = defaultValue;
    }

    public object GetValue(object target)
    {
        return this.provider.GetValue(target) ?? this.defaultValue;
    }

    public void SetValue(object target, object value)
    {
        this.provider.SetValue(target, value);
    }
}