RestSharp反序列化非标准JSON数组,DataGridView无数据显示求助
解决RestSharp反序列化动态键JSON并绑定DataGridView的问题
你的问题核心在于JSON的data数组里每个元素都是仅包含一个动态设备ID键的对象,而你当前的实体类结构虽然能完成反序列化,但生成的List<GpsEquipo>里每个GpsEquipo的Dictionary只有一个键值对,DataGridView无法自动解析这种嵌套结构,导致数据无法显示。另外还有一个小问题:JSON里的status是数字类型(200),但你定义的RootObject里status是string,这会导致反序列化时类型不匹配。
下面给你两种可行的解决方案:
方案1:修改实体类结构并手动转换数据
这种方式简单直接,不需要自定义转换器,适合快速解决问题:
步骤1:调整实体类
首先修正RootObject的status类型,同时将data改为List<Dictionary<string, GpsOdometro>>,因为数组里的每个元素本身就是一个单键字典:
public class GpsOdometro { public string Fecha { get; set; } public string Kilometros { get; set; } public string Odometro { get; set; } public string Horas { get; set; } } public class RootObject { public int status { get; set; } // 改为int匹配JSON的数字类型 public List<Dictionary<string, GpsOdometro>> data { get; set; } }
然后创建一个用于DataGridView显示的扁平实体类(把设备ID和GPS数据放在同一层级):
public class GpsDisplayItem { public string DeviceId { get; set; } // 新增设备ID字段 public string Fecha { get; set; } public string Kilometros { get; set; } public string Odometro { get; set; } public string Horas { get; set; } }
步骤2:反序列化并转换数据
反序列化后,把嵌套的字典结构转换成扁平的GpsDisplayItem列表,这样就能直接绑定到DataGridView:
IRestResponse json = client.Execute(request); RootObject result = JsonConvert.DeserializeObject<RootObject>(json.Content); // 转换为适合显示的扁平结构 var displayList = result.data .SelectMany(dict => dict.Select(kv => new GpsDisplayItem { DeviceId = kv.Key, Fecha = kv.Value.Fecha, Kilometros = kv.Value.Kilometros, Odometro = kv.Value.Odometro, Horas = kv.Value.Horas })) .ToList(); // 绑定到DataGridView DgOdometro.DataSource = displayList;
方案2:自定义JsonConverter一步到位
如果你希望反序列化直接得到可绑定的对象,可以自定义一个JSON转换器,自动把每个单键对象转换成包含设备ID的实体:
步骤1:创建显示实体和转换器
public class GpsDisplayItem { public string DeviceId { get; set; } public string Fecha { get; set; } public string Kilometros { get; set; } public string Odometro { get; set; } public string Horas { get; set; } } public class GpsItemConverter : JsonConverter<GpsDisplayItem> { public override GpsDisplayItem ReadJson(JsonReader reader, Type objectType, GpsDisplayItem existingValue, bool hasExistingValue, JsonSerializer serializer) { // 加载当前JSON对象 var jObject = JObject.Load(reader); // 获取唯一的设备ID键 var deviceId = jObject.Properties().First().Name; // 解析对应的GPS数据 var odometroData = jObject.Properties().First().Value.ToObject<GpsOdometro>(); return new GpsDisplayItem { DeviceId = deviceId, Fecha = odometroData.Fecha, Kilometros = odometroData.Kilometros, Odometro = odometroData.Odometro, Horas = odometroData.Horas }; } public override void WriteJson(JsonWriter writer, GpsDisplayItem value, JsonSerializer serializer) { // 如果不需要序列化回去,可以留空或抛出异常 throw new NotImplementedException(); } }
步骤2:调整RootObject并应用转换器
public class GpsOdometro { public string Fecha { get; set; } public string Kilometros { get; set; } public string Odometro { get; set; } public string Horas { get; set; } } public class RootObject { public int status { get; set; } // 对data字段应用自定义转换器 [JsonConverter(typeof(GpsItemConverter))] public List<GpsDisplayItem> data { get; set; } }
步骤3:反序列化并直接绑定
现在反序列化后可以直接把result.data绑定到DataGridView:
IRestResponse json = client.Execute(request); RootObject result = JsonConvert.DeserializeObject<RootObject>(json.Content); DgOdometro.DataSource = result.data;
两种方案都能解决你的问题,方案1更简单,方案2更优雅,适合后续扩展。
内容的提问来源于stack exchange,提问作者Limberg A.
相关产品推荐
相关产品推荐

