Json反序列化报错:无法将JObject转换为JToken的原因与解决
问题:反序列化JSON时抛出“Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken”异常
配置JSON
"printers": { "default": "Kyocera ECOSYS M6230cidn KX", "userMappings": [ { "user": "050327", "printer": "SG Fanelli" }, { "user": "050139", "printer": "SGPB" }, { "user": "050115", "printer": "SG Holenstein" } ] }
定义的DTO类
public class PrintersDto { public string Default { get; set; } public IEnumerable<UserPrinterDto> UserMappings { get; set; } = new List<UserPrinterDto>(); } public class UserPrinterDto { public string User { get; set; } public string Printer { get; set; } }
加载配置的代码
public PrintersDto GetPrintersConfig() { using (var configFileStream = FileIoService.ReadFile(ConfigFilePath)) { using (var reader = new StreamReader(configFileStream)) { var jsonString = reader.ReadToEnd(); _configData = (JObject) JsonConvert.DeserializeObject(jsonString); var jtoken = _configData.SelectToken("printers"); return jtoken.Value<PrintersDto>(); } } }
抛出的异常
Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken
异常原因
Value<T>()方法仅适用于从**值类型的JToken(如JValue)**中提取对应类型的值,而SelectToken("printers")返回的是JObject(JToken的子类,代表一个JSON对象),并非单纯的JValue,直接调用Value<T>()会触发类型转换失败的异常。
解决方法
有两种可行的修复方式:
方法1:使用ToObject<T>()替代Value<T>()
JObject提供的ToObject<T>()方法可以直接将自身反序列化为指定的DTO类型,修改后的代码如下:
public PrintersDto GetPrintersConfig() { using (var configFileStream = FileIoService.ReadFile(ConfigFilePath)) { using (var reader = new StreamReader(configFileStream)) { var jsonString = reader.ReadToEnd(); _configData = (JObject) JsonConvert.DeserializeObject(jsonString); var jtoken = _configData.SelectToken("printers"); return jtoken.ToObject<PrintersDto>(); // 替换为ToObject方法 } } }
方法2:直接反序列化为目标类型(更简洁)
如果不需要保留全局的_configData JObject,可以跳过中间解析步骤,直接完成反序列化:
// 子方式1:定义根对象类 public class ConfigRoot { public PrintersDto Printers { get; set; } } public PrintersDto GetPrintersConfig() { using (var configFileStream = FileIoService.ReadFile(ConfigFilePath)) { using (var reader = new StreamReader(configFileStream)) { var jsonString = reader.ReadToEnd(); var root = JsonConvert.DeserializeObject<ConfigRoot>(jsonString); return root.Printers; } } } // 子方式2:直接反序列化printers节点 public PrintersDto GetPrintersConfig() { using (var configFileStream = FileIoService.ReadFile(ConfigFilePath)) { using (var reader = new StreamReader(configFileStream)) { var jsonString = reader.ReadToEnd(); var jObject = (JObject)JsonConvert.DeserializeObject(jsonString); return JsonConvert.DeserializeObject<PrintersDto>(jObject["printers"].ToString()); } } }
内容的提问来源于stack exchange,提问作者BennoDual
相关产品推荐
相关产品推荐

