C#使用System.Text.Json有条件序列化Link对象为字符串的问题咨询
你遇到的报错核心原因是项目使用了 System.Text.Json 的源生成序列化模式,自定义 Converter 中调用默认序列化时,临时构造的配置没有绑定预先生成的序列化元数据,因此无法找到 Link 类型的映射信息。
排查步骤
- 首先确认序列化配置:检查项目中是否定义了继承自
JsonSerializerContext的分部类,且序列化/反序列化方法传入了该上下文实例,而非使用默认的反射序列化模式。 - 检查自定义 Converter 逻辑:如果是参考通用方案新建了移除当前 Converter 的
JsonSerializerOptions实例,该实例未关联你的源生成上下文,就会抛出找不到元数据的错误。 - 验证
JsonSerializable特性的标注位置:源生成的JsonSerializable特性必须标注在自定义的JsonSerializerContext分部类上才会生效,直接标注在Link实体类上无效。
解决方案
方案1:调整 Converter 默认序列化逻辑(推荐)
修改自定义 LinkConverter 的读写逻辑,避免重复构造无元数据的配置:
public class LinkConverter : JsonConverter<Link> { // 自定义判断条件:满足则序列化为URL字符串,可替换为你的业务规则 private static bool ShouldCollapseToUrl(Link link) { return string.IsNullOrEmpty(link.Rel) && (link.Rels == null || !link.Rels.Any()) // 补充其他属性为空的判断逻辑 && !string.IsNullOrEmpty(link.Href); } public override void Write(Utf8JsonWriter writer, Link value, JsonSerializerOptions options) { if (ShouldCollapseToUrl(value)) { writer.WriteStringValue(value.Href); return; } // 构造排除当前Converter的新配置,避免循环调用 var newOptions = new JsonSerializerOptions(options); var currentConverter = newOptions.Converters.OfType<LinkConverter>().FirstOrDefault(); if (currentConverter != null) { newOptions.Converters.Remove(currentConverter); } // 绑定源生成上下文的TypeInfoResolver newOptions.TypeInfoResolver = ActivityPubJsonContext.Default; JsonSerializer.Serialize(writer, value, newOptions); } public override Link Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 支持字符串格式的反序列化 if (reader.TokenType == JsonTokenType.String) { return new Link(reader.GetString()); } // 对象格式走默认反序列化 var newOptions = new JsonSerializerOptions(options); var currentConverter = newOptions.Converters.OfType<LinkConverter>().FirstOrDefault(); if (currentConverter != null) { newOptions.Converters.Remove(currentConverter); } newOptions.TypeInfoResolver = ActivityPubJsonContext.Default; return JsonSerializer.Deserialize<Link>(ref reader, newOptions)!; } }
注意把代码中的
ActivityPubJsonContext替换为你项目中实际定义的JsonSerializerContext子类名。
方案2:切换为反射序列化模式(临时验证用)
如果不需要源生成的性能优化,可以直接修改序列化配置,关闭源生成模式,使用反射序列化,即可兼容通用的自定义Converter逻辑:
var options = new JsonSerializerOptions { // 其他原有配置 TypeInfoResolver = null, // 不使用源生成的TypeInfo };
内容的提问来源于stack exchange,提问作者SuperMeip
相关产品推荐
相关产品推荐

