.NET 8自定义JsonConverter的Read方法未触发原因排查
问题分析与解决方案
核心问题1:Read方法未执行的原因
虽然EmailadressenConverter.CanConvert返回true,但序列化器未调用Read方法,大概率是因为转换器的注册优先级或类型匹配的隐性问题。默认情况下,JsonConverter<Emails>的CanConvert基类实现仅匹配typeof(Emails),但在处理可空引用类型(Emails?)时,可能存在序列化器的隐性判断偏差。此外,如果序列化器认为可以通过构造函数直接绑定类型(即使实际无法完成),也会跳过转换器。
核心问题2:转换器逻辑与JSON结构不匹配
你的JSON结构是嵌套的{"email": {"value":"foo@bar.com"}},但转换器代码中一直在查找Emailadressen.PrimairEmailAdres字段(该类未在代码中定义),完全无法匹配实际JSON结构,即便Read方法执行,也会返回null。
修复步骤
1. 修正转换器的CanConvert方法
显式指定匹配类型,消除隐性判断问题:
public override bool CanConvert(Type typeToConvert) { // 明确匹配Emails类型,包括可空引用类型(运行时与非可空一致) return typeToConvert == typeof(Emails); }
2. 重写Read方法适配JSON结构
根据实际JSON的嵌套结构,调整解析逻辑:
public override Emails? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) return null; string? emailValue = null; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) break; if (reader.TokenType == JsonTokenType.PropertyName) { var propName = reader.GetString(); // 匹配外层的"email"属性 if (string.Equals(propName, nameof(Emails.Email), StringComparison.CurrentCultureIgnoreCase)) { // 进入email对象 if (reader.Read() && reader.TokenType == JsonTokenType.StartObject) { while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) break; if (reader.TokenType == JsonTokenType.PropertyName) { var innerPropName = reader.GetString(); // 匹配内层的"value"属性 if (string.Equals(innerPropName, nameof(Emailadres.Value), StringComparison.CurrentCultureIgnoreCase)) { if (reader.Read() && reader.TokenType == JsonTokenType.String) { emailValue = reader.GetString(); } } } } } } } } return string.IsNullOrEmpty(emailValue) ? null : new Emails(emailValue); }
3. 修正测试代码中的JSON字符串
原代码中的JSON字符串写法存在语法错误,改为逐字字符串避免转义问题:
var json = @"{ ""emailZakelijk"": { ""email"": { ""value"":""foo@bar.com"" } } }";
4. 强制转换器生效(可选)
如果仍存在转换器未被调用的情况,可以直接在Emails类上标记转换器属性,绕过全局注册的潜在问题:
[JsonConverter(typeof(EmailadressenConverter))] public class Emails { public Emails(string primairEmailadres) { Email = new Emailadres(primairEmailadres); } public Emailadres Email { get; set; } }
内容的提问来源于stack exchange,提问作者Martijn
相关产品推荐
相关产品推荐

