I am trying to perform custom serialisation, all the happy path code works but the null value path is not behaving as I'd like.
I have set the serializer settings to NullValueHandling.Ignore
and other parts of my object graph that are null (and don't use my custom serialization) have the null values removed. It looks like the Newtonsoft serializer writes to a string builder so we should be able to 'rewind' any written json tokens but I don't see how to not write anything.
Doing nothing and just returning causes the serializer to throw an exception as the json would be invalid.
Any clues?
public class SpecialConvertor : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null || (int)value == 0)
{
if (serializer.NullValueHandling == NullValueHandling.Ignore)
{
//how to make this work?
}
else
{
writer.WriteNull();
}
return;
}
// the rest of WriteJson
}
// the rest of SpecialConvertor
}
NullValueHandling
is for object references. In your example, your value is an integer. To omit integer properties with default values, use the setting DefaultValueHandling = DefaultValueHandling.Ignore
.
The null
check in WriteJson()
should not be necessary because Json.NET never calls the converter with a null value. Instead, it writes the name & null value itself -- or not, if NullValueHandling == NullValueHandling.Ignore
. So checking for null and rewinding should never be required.
A null value for an object property might still get written when null value handling or default value handling are Ignore
if one of your converters writes it explicitly in WriteJson
. To prevent that, you can check the settings and skip nulls like so:
public class MyClassConverter : JsonConverter
{
const string Prefix = "My Value Is: ";
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var myClass = (MyClass)value;
writer.WriteStartObject();
if (myClass.StringValue != null
|| (serializer.NullValueHandling != NullValueHandling.Ignore
&& (serializer.DefaultValueHandling & DefaultValueHandling.Ignore) != DefaultValueHandling.Ignore))
{
writer.WritePropertyName("StringValue");
if (myClass.StringValue == null)
writer.WriteNull();
else
serializer.Serialize(writer, Prefix + myClass.StringValue);
}
writer.WriteEndObject();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var s = (string)JValue.Load(reader);
if (s.StartsWith(Prefix))
s = s.Substring(Prefix.Length);
return s;
}
public override bool CanConvert(Type objectType) { return objectType == typeof(MyClass); }
}
[JsonConverter(typeof(MyClassConverter))]
public class MyClass
{
public string StringValue { get; set; }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With