.NET7下Native AOT编译JsonSerializer.Deserialize报错及源生成无效问题
.NET7 Native AOT下JsonSerializer.Deserialize编译警告问题解决
问题场景
使用.NET7框架,以下代码在调试或非AOT编译时运行正常,但Native AOT编译时出现警告:
var Options=new JsonSerializerOptions() { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All) }; List<ThemeModel> ThemeList = JsonSerializer.Deserialize<List<ThemeModel>>(ThemeString, Options)??new List<ThemeModel>();
编译警告信息
1>,D:\Test\Theme.cs(38,30,38,104): warning IL3050: Using member 'System.Text.Json.JsonSerializer.Deserialize(String, Type, JsonSerializerOptions)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications. 1>,D:\Test\Theme.cs(38,30,38,104): warning IL2026: Using member 'System.Text.Json.JsonSerializer.Deserialize(String, Type, JsonSerializerOptions)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.
用户尝试的源生成代码(仍触发警告)
public class ThemeModel { public string ThemeKey { get; set; } = ""; public enum ThemeValueTypeEnum { LinearGradientBrush, SolidColorBrush, SVGStyle, ImageStyle } public ThemeValueTypeEnum ThemeValueType { get; set; } public string ThemeValue { get; set; } = ""; } [JsonSerializable(typeof(ThemeModel))] [JsonSerializable(typeof(string))] [JsonSerializable(typeof(ThemeValueTypeEnum))] internal partial class ThemeModelSourceGenerationContext : JsonSerializerContext { } public void LoadTheme(string ThemeString) { var Options = new JsonSerializerOptions() { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All), TypeInfoResolver = ThemeModelSourceGenerationContext.Default }; List<ThemeModel> ThemeList = JsonSerializer.Deserialize<List<ThemeModel>>(ThemeString, Options)??new List<ThemeModel>(); }
问题分析
- 源生成上下文未注册
List<ThemeModel>类型,导致框架无法为集合生成静态序列化代码 - 仍在调用依赖动态代码生成的泛型重载,未使用源生成专属的
JsonTypeInfo或JsonSerializerContext重载
解决步骤
1. 补充源生成上下文的集合类型注册
在ThemeModelSourceGenerationContext中添加List<ThemeModel>的注册,让源生成器为集合生成静态代码:
[JsonSerializable(typeof(ThemeModel))] [JsonSerializable(typeof(List<ThemeModel>))] // 新增集合类型注册 [JsonSerializable(typeof(ThemeValueTypeEnum))] internal partial class ThemeModelSourceGenerationContext : JsonSerializerContext { }
2. 使用源生成专属的反序列化重载
直接通过源生成上下文获取类型信息,调用静态化的重载,避免动态代码路径:
public void LoadTheme(string ThemeString) { var options = new JsonSerializerOptions() { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All) }; // 使用源生成的List<ThemeModel>类型信息进行反序列化 List<ThemeModel> themeList = JsonSerializer.Deserialize(ThemeString, ThemeModelSourceGenerationContext.Default.ListThemeModel) ?? new List<ThemeModel>(); }
或者合并自定义配置与源生成上下文选项:
public void LoadTheme(string ThemeString) { List<ThemeModel> themeList = JsonSerializer.Deserialize<List<ThemeModel>>(ThemeString, new JsonSerializerOptions(ThemeModelSourceGenerationContext.Default.Options) { Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(UnicodeRanges.All) }) ?? new List<ThemeModel>(); }
原理说明
Native AOT编译要求所有代码在编译期静态确定,传统的JsonSerializer.Deserialize泛型重载依赖运行时动态生成代码分析类型元数据,不符合AOT要求。通过源生成器,编译器会在编译期提前生成对应类型(包括集合)的序列化/反序列化代码,结合JsonTypeInfo或JsonSerializerContext的重载,确保代码完全静态化,适配Native AOT编译环境。
内容的提问来源于stack exchange,提问作者Melon NG
相关产品推荐
相关产品推荐

