Linux环境下JsonSerializer.Deserialize反序列化找不到类Setter问题
问题分析与解决
问题现象
运行代码时抛出以下错误:
System.InvalidOperationException: JsonPropertyInfo 'test' defined in type 'Test.Config' is marked required but does not specify a setter.
- 移除
JsonRequired特性后不再报错,但反序列化得到的是配置类的默认实例(test值为1),而非JSON文件中的设定值(2) - 该问题仅在Linux环境下出现,Windows环境可正常完成反序列化
相关代码与文件
配置类定义
public class Config { [JsonRequired] public int test { get; set; } = 1; }
反序列化逻辑
JsonSerializerOptions options = new JsonSerializerOptions(); using (StreamReader reader = new StreamReader(filePath)){ config = JsonSerializer.Deserialize<Config>(reader.BaseStream, options); }
JSON配置文件内容
{ "test": 2 }
原因分析
这是.NET System.Text.Json在跨平台下的JIT编译行为差异导致的:
- Windows环境的JIT编译会自动为自动属性生成可被序列化器识别的setter元数据,因此能正常处理
- Linux环境的CoreCLR JIT对属性元数据的校验更严格,即便代码里显式写了
set;,优化后的元数据仍可能被判定为“未指定setter”,触发JsonRequired的校验错误
另外,移除特性后得到默认实例的问题,大概率是Linux下文件权限或路径问题导致配置文件未被正确读取,而非序列化逻辑本身。
解决办法
方法1:显式声明setter访问修饰符(推荐)
给属性setter加上public修饰符,确保跨平台元数据识别一致:
public class Config { [JsonRequired] public int test { get; public set; } = 1; }
方法2:调整序列化器配置
修改JsonSerializerOptions,放宽属性访问权限的校验:
JsonSerializerOptions options = new JsonSerializerOptions { PropertyVisibility = JsonPropertyVisibility.All, PropertyNameCaseInsensitive = true };
方法3:移除必填特性并校验文件读取
如果不需要强制校验必填字段,可移除JsonRequired,同时增加文件存在性与权限检查:
public class Config { public int test { get; set; } = 1; } // 反序列化前先检查文件 if (!File.Exists(filePath)) { throw new FileNotFoundException("配置文件不存在", filePath); } // 检查文件是否可读 try { using (var stream = File.OpenRead(filePath)) {} } catch (UnauthorizedAccessException) { throw new UnauthorizedAccessException("无配置文件读取权限"); } using (StreamReader reader = new StreamReader(filePath)) { config = JsonSerializer.Deserialize<Config>(reader.BaseStream, options); }
内容的提问来源于stack exchange,提问作者John Moffitt
相关产品推荐
相关产品推荐

