I am trying to override the serialized value of a nullable object property using a JsonConverterAttribute pointing to a Custom JsonConverter
In the example shown below I am able to properly override the serialized value of a non-nullable primitive type (MyInt).
However, the MyConverter.WriteJson method does not seem to get called when the property is nullable and not initialized (OptInt)
namespace Project
{
using System;
using Newtonsoft.Json;
public class MyConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => true;
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
writer.WriteValue(123);
}
public override bool CanRead => false;
public override object? ReadJson(JsonReader reader, Type type, object? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class MyModel
{
public int Int { get; set; }
[JsonConverter(typeof(MyConverter))]
public int MyInt { get; set; }
[JsonConverter(typeof(MyConverter))]
[JsonProperty("OptInt", NullValueHandling = NullValueHandling.Ignore)]
public int? OptInt { get; set; }
}
}
[Fact]
public void TestOptIntSet()
{
var myObject = new MyModel(){OptInt = 666};
var json = JsonConvert.SerializeObject(myObject);
Assert.Equal("{\"Int\":0,\"MyInt\":123,\"OptInt\":123}", json);
// Passed
}
[Fact]
public void TestEmptyModel()
{
var myObject = new MyModel();
var json = JsonConvert.SerializeObject(myObject);
Assert.Equal("{\"Int\":0,\"MyInt\":123,\"OptInt\":123}", json);
// Assert.Equal() Failure
// ↓ (pos 30)
// Expected: ···MyInt":123,"OptInt":123}
// Actual: ···MyInt":123,"OptInt":null}
// ↑ (pos 30)
}
How can I override the null value in the serialized output for a specific nullable property when it is not set ?
Note: NullValueHandling is set to Include by default, setting [JsonProperty("OptInt", NullValueHandling = NullValueHandling.Ignore)] would simply omit OptInt in the serialized output:
// Assert.Equal() Failure
// ↓ (pos 20)
// Expected: ···MyInt":123,"OptInt":123}
// Actual: ···MyInt":123}
// ↑ (pos 20)