使用System.Text.Json反序列化JSON文件遇异常,求解决方案
System.Text.Json反序列化异常修复方案
问题场景
你在使用System.Text.Json反序列化JSON文件时抛出异常,相关代码和JSON结构如下:
主程序代码
using System; using System.IO; using System.Text.Json; namespace Framework.Test { public class Program { static void Main(string[] args) { new JSONInfo(); // 读取JSON文件 string fileName = "config.json"; string jsonString = File.ReadAllText(fileName); MyAttribute weatherForecast = JsonSerializer.Deserialize<MyAttribute>(jsonString)!; Console.WriteLine($"D: {weatherForecast?.APP}"); } } }
实体类代码
using System; namespace Framework { public class JSONInfo { [MyAttribute] public string? APP; } [AttributeUsage(AttributeTargets.Field)] public class MyAttribute : Attribute { public virtual object? APP { get; set;} } }
JSON文件内容
{ "app":{ "AppName": "PZ", "Ver": "1.0.0", "AppID": "00001", "GameRunState":"Debug", "Logger": true, "AppLocalPath":"", "AssetsPath": "/Assets/" }, "preload":{ "LoadType1":"Video", "LoadItem1":"" } }
错误原因
- 误用Attribute作为反序列化目标:
MyAttribute是继承自Attribute的自定义特性,作用是标记元数据,不是用来承载JSON数据的实体类,System.Text.Json无法将JSON反序列化为Attribute类型。 - 实体结构与JSON不匹配:JSON根节点包含
app和preload两个对象,但你没有定义对应的实体类来映射这个结构;同时JSON中的app对象包含多个属性,你也没有对应的类来承载。 - 大小写不匹配:System.Text.Json默认大小写敏感,JSON中的
app是小写,而你代码中的属性名称是大写APP,即使结构正确也无法映射。
修复步骤
- 定义匹配JSON结构的实体类:创建根实体类,包含
App和Preload属性,分别对应JSON中的app和preload对象;再创建AppConfig和PreloadConfig类来映射对应的子对象属性。 - 使用
JsonPropertyName处理大小写映射:因为JSON中的键是小写/混合大小写,实体类属性用PascalCase的话,需要用该特性指定对应的JSON键名。 - 替换反序列化的目标类型:将反序列化的目标改为新定义的根实体类。
修复后完整代码
实体类代码
using System; using System.Text.Json.Serialization; namespace Framework { // 根实体类,匹配JSON结构 public class ConfigRoot { [JsonPropertyName("app")] public AppConfig? App { get; set; } [JsonPropertyName("preload")] public PreloadConfig? Preload { get; set; } } // 映射JSON中的app对象 public class AppConfig { [JsonPropertyName("AppName")] public string? AppName { get; set; } [JsonPropertyName("Ver")] public string? Version { get; set; } [JsonPropertyName("AppID")] public string? AppId { get; set; } [JsonPropertyName("GameRunState")] public string? GameRunState { get; set; } [JsonPropertyName("Logger")] public bool Logger { get; set; } [JsonPropertyName("AppLocalPath")] public string? AppLocalPath { get; set; } [JsonPropertyName("AssetsPath")] public string? AssetsPath { get; set; } } // 映射JSON中的preload对象 public class PreloadConfig { [JsonPropertyName("LoadType1")] public string? LoadType1 { get; set; } [JsonPropertyName("LoadItem1")] public string? LoadItem1 { get; set; } } // 保留原来的Attribute(如果需要元数据标记用) [AttributeUsage(AttributeTargets.Field)] public class MyAttribute : Attribute { public virtual object? APP { get; set;} } public class JSONInfo { [MyAttribute] public string? APP; } }
主程序代码
using System; using System.IO; using System.Text.Json; namespace Framework.Test { public class Program { static void Main(string[] args) { // 读取JSON文件 string fileName = "config.json"; string jsonString = File.ReadAllText(fileName); // 反序列化为正确的根实体类 ConfigRoot config = JsonSerializer.Deserialize<ConfigRoot>(jsonString)!; // 输出测试 Console.WriteLine($"AppName: {config?.App?.AppName}"); Console.WriteLine($"Version: {config?.App?.Version}"); Console.WriteLine($"GameRunState: {config?.App?.GameRunState}"); Console.WriteLine($"LoadType1: {config?.Preload?.LoadType1}"); } } }
运行结果
执行后会输出:
AppName: PZ Version: 1.0.0 GameRunState: Debug LoadType1: Video
内容的提问来源于stack exchange,提问作者HAF
相关产品推荐
相关产品推荐

