使用JSON.NET转换特定JSON时出现类型转换错误求助
问题描述
我正在为公司应用实现新功能,之前团队用JSON.NET完成过类似反序列化,现在复用方式时遇到转换错误:无法将System.String转换为HistoryList。
待反序列化的JSON
"{ \"@type\":[\"IN.history.1\"], \"@self\":\"/history\", \"history\":[ \"195166208; 2021-09-06T11:48:26.164; User Modified; TA_NONE; 1.1.System.4.1; \\u0003D\\u0001 = \\u0001\\n\\u0006 = Standard\\nIsMandatory = No\\nModifiedUser_ID = 3\\nModifiedUser_Name = BIS Benutzer\\nModifierUser_ID = 3\\nModifierUser_Name = BIS Benutzer\\nSource_Name = RPS\\nSource_ReportingNumber = 0\\n\" ] }"
自定义类定义
public class HistoryList { public string eventID { get; set; } public string timestamp { get; set; } public string eventName { get; set; } public string ta { get; set; } public string siid { get; set; } public string parameters { get; set; } } public class GetHistory { public List<string> type { get; set; } public string self { get; set; } public List<HistoryList> history { get; set; } }
反序列化代码
internal List<HistoryList> GetHistory(int maxEvents) { string response = GetJson(_url + "/history?maxevents=" + Convert.ToString(maxEvents)); response = response.Replace("@", ""); return JsonConvert.DeserializeObject<MAP5000Classes.GetHistory>(response).history; }
问题根源
JSON里的history数组存储的是单个字符串值,但你的GetHistory类里把history定义成了List<HistoryList>,JSON.NET无法自动把字符串转换成自定义的HistoryList对象,所以抛出类型转换错误。
解决方法
方法1:先反序列化为字符串列表,再手动分割转换
修改GetHistory类的history属性类型为List<string>,反序列化后再把每个字符串分割成HistoryList对象:
- 更新类定义:
public class GetHistory { public List<string> type { get; set; } public string self { get; set; } public List<string> history { get; set; } // 改为字符串列表 }
- 修改反序列化方法:
internal List<HistoryList> GetHistory(int maxEvents) { string response = GetJson(_url + "/history?maxevents=" + Convert.ToString(maxEvents)); response = response.Replace("@", ""); var rawHistory = JsonConvert.DeserializeObject<MAP5000Classes.GetHistory>(response).history; // 转换每个字符串为HistoryList return rawHistory.Select(str => { // 按分号分割,处理换行和多余空格 var parts = str.Split(';') .Select(p => p.Trim().Replace("\r\n", "").Replace("\n", "")) .Where(p => !string.IsNullOrEmpty(p)) .ToArray(); return new HistoryList { eventID = parts[0], timestamp = parts[1], eventName = parts[2], ta = parts[3], siid = parts[4], parameters = parts[5] }; }).ToList(); }
方法2:使用JSON.NET自定义转换器
如果想保留List<HistoryList>的定义,可以自定义一个JsonConverter来处理字符串到HistoryList的转换:
- 创建转换器:
public class HistoryListConverter : JsonConverter<HistoryList> { public override HistoryList ReadJson(JsonReader reader, Type objectType, HistoryList existingValue, bool hasExistingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.String) { var str = reader.Value.ToString(); var parts = str.Split(';') .Select(p => p.Trim().Replace("\r\n", "").Replace("\n", "")) .Where(p => !string.IsNullOrEmpty(p)) .ToArray(); return new HistoryList { eventID = parts[0], timestamp = parts[1], eventName = parts[2], ta = parts[3], siid = parts[4], parameters = parts[5] }; } throw new JsonSerializationException("Expected string for HistoryList"); } public override void WriteJson(JsonWriter writer, HistoryList value, JsonSerializer serializer) { // 若需序列化可自行实现,此处暂不处理 throw new NotImplementedException(); } }
- 在类属性上标记转换器:
public class GetHistory { public List<string> type { get; set; } public string self { get; set; } [JsonConverter(typeof(HistoryListConverter))] public List<HistoryList> history { get; set; } }
- 反序列化代码无需修改,直接沿用原方法即可。
注意事项
- 分割字符串时要处理换行符和多余空格,避免出现空值或无效内容。
- 若
history内的字符串格式可能变动,建议添加异常处理逻辑,防止索引越界。
内容的提问来源于stack exchange,提问作者Alaggaerion
相关产品推荐
相关产品推荐

