You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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对象:

  1. 更新类定义:
public class GetHistory
{
    public List<string> type { get; set; }
    public string self { get; set; }
    public List<string> history { get; set; } // 改为字符串列表
}
  1. 修改反序列化方法:
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的转换:

  1. 创建转换器:
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();
    }
}
  1. 在类属性上标记转换器:
public class GetHistory
{
    public List<string> type { get; set; }
    public string self { get; set; }
    [JsonConverter(typeof(HistoryListConverter))]
    public List<HistoryList> history { get; set; }
}
  1. 反序列化代码无需修改,直接沿用原方法即可。

注意事项

  • 分割字符串时要处理换行符和多余空格,避免出现空值或无效内容。
  • 若history内的字符串格式可能变动,建议添加异常处理逻辑,防止索引越界。

内容的提问来源于stack exchange,提问作者Alaggaerion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 09:24:20