System.Text.Json序列化含Type属性对象反序列化空值问题排查
问题根因
反序列化返回null是当前实现的两处逻辑缺陷导致:
- 序列化输出的类型标识不标准:Write方法中使用
Type.ToString()输出类型字符串,该方法的输出结果不保证和Type.FullName完全一致(特殊类型、嵌套类型会存在格式化差异),导致反序列化时拼接的程序集匹配串无法命中目标类型。 - 程序集未预加载:如果
MyAssembly1、MyAssembly2未被当前应用程序域提前加载,Type.GetType默认不会主动加载未引用的程序集,会直接返回null。
修复方案
修改后的转换器代码如下:
internal class TypeConverter : JsonConverter<Type> { // 静态构造函数预加载指定程序集,避免GetType找不到未加载的类型 static TypeConverter() { Assembly.Load(nameof(MyAssembly1)); Assembly.Load(nameof(MyAssembly2)); } public override Type Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { string typeFullName = reader.GetString(); if (string.IsNullOrWhiteSpace(typeFullName)) return null; // 按优先级匹配两个程序集中的类型 return Type.GetType($"{typeFullName}, {nameof(MyAssembly1)}", throwOnError: false) ?? Type.GetType($"{typeFullName}, {nameof(MyAssembly2)}", throwOnError: false); } public override void Write(Utf8JsonWriter writer, Type value, JsonSerializerOptions options) { // 输出标准的类型全限定名,保证反序列化匹配准确 writer.WriteStringValue(value.FullName); } }
如果修改后仍然返回null,可以临时将throwOnError设为true,查看具体异常信息排查匹配失败原因,常见原因包括类名拼写错误、命名空间变更、程序集版本不匹配等。
方案可行性与推荐建议
- 可控场景下可行:如果你完全掌握序列化、反序列化的两端环境,且JSON数据源完全可信,该方案可以正常使用,你已经限制了仅能加载指定的两个自定义程序集,大幅降低了类型注入的安全风险。
- 非可信场景绝对不推荐:如果JSON输入来自外部不可信来源,哪怕限制了程序集范围,仍有可能被利用构造恶意类型执行危险操作。
- 额外注意事项:需要保证序列化、反序列化两端的
MyAssembly1、MyAssembly2版本一致,类名、命名空间变更会导致历史序列化数据无法反序列化。
内容的提问来源于stack exchange,提问作者monadoboy007
相关产品推荐
相关产品推荐

