When I debug the test below, the code hits the CanConvert
method of the EmailadressenConverter
class and that method returns true
.
I was expecting the Read
method to get hit next, but this never happens, resulting in an object that has null
for property EmailZakelijk
.
Why is the Read
method not called?
I am using .NET 8, and this is my code:
public class EmailadressenConverter : JsonConverter<Emails>
{
public override bool CanConvert(Type typeToConvert)
{
return base.CanConvert(typeToConvert);
}
public override Emails? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var ctorEmail = "";
var optionalEmails = new List<string>();
var currentPropertyName = "";
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
break;
if (reader.TokenType == JsonTokenType.PropertyName)
{
currentPropertyName = reader.GetString()!;
continue;
}
if (string.Equals(currentPropertyName, nameof(Emailadressen.PrimairEmailAdres), StringComparison.CurrentCultureIgnoreCase))
ctorEmail = reader.GetString()!;
}
if (string.IsNullOrEmpty(ctorEmail))
return null;
return new Emails(ctorEmail);
}
public override void Write(Utf8JsonWriter writer, Emails value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WriteString(nameof(Emails.Email), value.Email.Value);
writer.WriteEndObject();
return;
}
}
public class Emails
{
public Emails(string primairEmailadres)
{
Email = new Emailadres(primairEmailadres);
}
public Emailadres Email { get; set; }
}
public class DummyMailClass
{
public Emails? EmailZakelijk { get; set; }
}
public class EmailadressenJsonConverterTests
{
[Fact]
public void Deserialize_only_primair_emailadres()
{
var json = """
{
"emailZakelijk": {
"email": {
"value":"[email protected]"
}
}
}
""";
var options = new JsonSerializerOptions();
//options.Converters.Clear();
options.Converters.Add(new EmailadressenConverter());
//options.Converters.Add(new EmailsConverterFactory());
var dmc = JsonSerializer.Deserialize<DummyMailClass>(json, options);
dmc.Should().NotBeNull();
dmc!.EmailZakelijk.Should().NotBeNull();
dmc.EmailZakelijk!.Email.Value.Should().Be("[email protected]");
}
}
public partial record Emailadres
{
public Emailadres(string value)
{
Value = value;
}
public string Value { get; private set; }
}
2
Answers
Turns out I hadn't set
PropertyNameCaseInsensitive
to true onJsonSerializerOptions
. Very frustrating, I thought this was true by default.When you declare the
JsonSerializerOptions
instance, the defaultPropertyNamingPolicy
isnull
. Thus, it is unable to convert for theemailZakelijk
JSON object as it is in camel case.So either you need to provide
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
Or specify
PropertyNameCaseInsensitive = true
inJsonSerializerOptions
.Note that I get the exception:
Thus, I revamp the
Read
logic as below: