Telegram聊天JSON反序列化问题:text字段类型不一致如何处理?
解决Telegram导出JSON中Text字段类型不一致的反序列化问题
这确实是Telegram导出JSON时的常见坑——纯文本消息的text是字符串,带格式(提及、链接等)的消息会把text变成数组,直接用固定类型反序列化自然会触发类型不匹配的错误。下面给你两种实用方案,按需选择即可:
方案1:自定义Json转换器(自动合并为纯文本)
如果你只需要提取消息的完整文本内容,不需要保留格式细节,自定义转换器是最省心的方式,它会自动把字符串/数组统一转换成单个字符串:
步骤1:实现自定义转换器
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Text; public class TextConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(string); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); // 判断当前token类型,分别处理 if (token.Type == JTokenType.String) { return token.ToString(); } else if (token.Type == JTokenType.Array) { var sb = new StringBuilder(); // 遍历数组中的每个元素,拼接所有text内容 foreach (var item in token.Children()) { if (item.Type == JTokenType.String) { sb.Append(item.ToString()); } else if (item.Type == JTokenType.Object) { sb.Append(item["text"]?.ToString()); } } return sb.ToString(); } return null; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
步骤2:修正模型类(键名映射+绑定转换器)
注意要给属性加上JsonProperty特性,确保和JSON的键名一一对应(比如JSON里的id对应模型的ID,from_id对应fromID),再给text字段绑定自定义转换器:
public class JSONObject { [JsonProperty("id")] public int ID { get; set; } [JsonProperty("type")] public string Type { get; set; } [JsonProperty("date")] public string Date { get; set; } [JsonProperty("edited")] public string Edited { get; set; } [JsonProperty("from")] public string From { get; set; } [JsonProperty("from_id")] public int FromID { get; set; } [JsonProperty("photo")] public string Photo { get; set; } [JsonProperty("width")] public int Width { get; set; } [JsonProperty("height")] public int Height { get; set; } [JsonProperty("text")] [JsonConverter(typeof(TextConverter))] public string Text { get; set; } }
步骤3:正常反序列化
现在你原来的代码就能正常运行了:
List<JSONObject> jsonObjects = JsonConvert.DeserializeObject<List<JSONObject>>(File.ReadAllText(openFileDialog.FileName));
方案2:用JToken保留格式信息
如果你需要保留消息的格式细节(比如区分普通文本、提及、链接),可以把text字段定义为JToken类型,兼容两种数据结构:
修改模型类
public class JSONObject { [JsonProperty("id")] public int ID { get; set; } [JsonProperty("type")] public string Type { get; set; } [JsonProperty("date")] public string Date { get; set; } [JsonProperty("edited")] public string Edited { get; set; } [JsonProperty("from")] public string From { get; set; } [JsonProperty("from_id")] public int FromID { get; set; } [JsonProperty("photo")] public string Photo { get; set; } [JsonProperty("width")] public int Width { get; set; } [JsonProperty("height")] public int Height { get; set; } [JsonProperty("text")] public JToken Text { get; set; } }
处理Text内容
反序列化后,根据Text的类型做不同处理:
foreach (var msg in jsonObjects) { if (msg.Text.Type == JTokenType.String) { string plainText = msg.Text.ToString(); // 处理纯文本消息 } else if (msg.Text.Type == JTokenType.Array) { foreach (var item in msg.Text.Children()) { if (item.Type == JTokenType.String) { string textPart = item.ToString(); // 处理普通文本片段 } else if (item.Type == JTokenType.Object) { string type = item["type"]?.ToString(); string text = item["text"]?.ToString(); // 根据类型区分处理 if (type == "mention") { // 处理@提及内容 } else if (type == "link") { // 处理链接内容 } } } } }
额外提醒
之前你的模型类没有加JsonProperty特性,这会导致ID、fromID等字段无法正确映射JSON里的id、from_id,一定要补上这个特性,否则这些字段会被反序列化为默认值。
内容的提问来源于stack exchange,提问作者Applesouce
相关产品推荐
相关产品推荐

