Nullable DateTime in Dictionary can't use custom converter to convert into empty string
kamyaw010 opened this issue · comments
I have some classes must be stored in a dictionary, but the code can not be uploaded, so I simplify the code and change it to below acts like the actual behavior.
But the Nullable<DateTime> can not trigger the converter and can't be serialize into an empty string, always serialize into null value, but actually I need it is an empty string so the front-end can accept it (front-end is a third-party library that can not be changed and some fields must have unless an empty string than null )
Source/destination types
JsonConvertTestClass Code ( have tried using [JsonConverter] attribute in DateTime? field ):
public record JsonConvertTestClass
{
public DateTime? GTime { get; set; }
public ParentClass Parent { get; set; } = new();
}
public record ParentClass
{
public DateTime? PTime { get; set; }
public ChildClass Child { get; set; } = new();
}
public record ChildClass
{
public DateTime? CTime { get; set; }
}
Custom Converter Code (no matter use JsonConverter or JsonConverter<DateTime?>):
public class DateTimeConverter : JsonConverter
{
public override bool CanWrite => true;
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime?) || objectType == typeof(DateTime);
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value is null)
{
writer.WriteValue(string.Empty);
}
else
{
writer.WriteValue(value);
}
}
}
Serialization Code:
var dict = new Dictionary<string, JsonConvertTestClass>();
for (var i = 0; i < 2; i++)
{
dict.Add(i.ToString(), new JsonConvertTestClass());
}
Console.WriteLine(JsonConvert.SerializeObject(dict, Formatting.Indented, new JsonSerializerSettings { Converters = { new DateTimeConverter() } }));
Source/destination JSON
{
"0": {
"GTime": null,
"Parent": {
"PTime": null,
"Child": {
"CTime": null
}
}
},
"1": {
"GTime": null,
"Parent": {
"PTime": null,
"Child": {
"CTime": null
}
}
}
}
Expected behavior
{
"0": {
"GTime": "",
"Parent": {
"PTime": "",
"Child": {
"CTime": ""
}
}
},
"1": {
"GTime": "",
"Parent": {
"PTime": "",
"Child": {
"CTime": ""
}
}
}
}
Actual behavior
All DateTime are null
Steps to reproduce
// Even use [JsonConverter] attribute doesn't work
Console.WriteLine(JsonConvert.SerializeObject(dict, Formatting.Indented, new JsonSerializerSettings { Converters = { new DateTimeConverter() } }));
The behavior you see is pretty much hard-coded:
As a (past) user of the library myself (only still using it in old legacy projects i didn't migrate to modern .NET), i have to admit that i can't muster much hope for this situation to be improved. That said, feel free to look at Newtonsoft.Json's development activities over the last few years and form your own opinion about it.
A work-around for this limitation is to write a converter that deals with the dictionary itself -- this way, this dictionary converter would then be able to iterate over the dictionary, deal with Nullable<T> values itself directly (thus bypassing hard-coded null checks in the serializer) and write/serialize the dictionary data to the JsonWriter in whatever way you need. If you feel this being too much work or your real situation is more complex and involving not just dictionaries with values from a limited number of relatively simple types, i would strongly suggest you contemplate switching to STJ if there are no roadblocks preventing you from doing that...
The behavior you see is pretty much hard-coded:
As a (past) user of the library myself (only still using it in old legacy projects i didn't migrate to modern .NET), i have to admit that i can't muster much hope for this situation to be improved. That said, feel free to look at Newtonsoft.Json's development activities over the last few years and form your own opinion about it.
A work-around for this limitation is to write a converter that deals with the dictionary itself -- this way, this dictionary converter would then be able to iterate over the dictionary, deal with Nullable values itself directly (thus bypassing hard-coded null checks in the serializer) and write/serialize the dictionary data to the JsonWriter in whatever way you need. If you feel this being too much work or your real situation is more complex and involving not just simple dictionaries, i would strongly suggest you contemplate switching to STJ if there are no roadblocks preventing you from doing that...
For some reasons, can't switch back to STJ :(
Seems can just hold a converter for the dictionary otherwise change this field into string? and handle it myself
Thanks.
For some reasons, can't switch back to STJ :(
That's unfortunate :-( because this would be easy-peasy to do in STJ https://dotnetfiddle.net/RDmNxD